让Dapper+SqlCE支持ntext数据类型和超过4000字符的存储
使用Dapper和SqlCE进行开发的时候,如果数据库的某字段是采用的ntext数据类型,并且在这个字段存储的数据超过了4000个字符,会报如下的错误:
Invalid parameter Size value '-1'. The value must be greater than or equal to 0.
在Google上以“dapper sqlce ntext”作为关键词搜索,可以找到如下两个解决办法:
1. Inserting a string larger then 4000 characters using Sql CE 4.0
2. Attempting to Modify Dapper to Support SQL Server CE's ntext type
这两个解决办法,要么通用性较差,要么使用比较麻烦。
通过查看Dapper的源码,发现Dapper在构造参数的动态方法中针对实体类属性为DbString的类型和数据类型为DbType.Xml进行了特别处理,我们也可以在这里入手,针对长字符串进行特别处理。
解决办法:
一、新建一个Attribute,用来标记需要特别处理的实体类属性;
[AttributeUsage(AttributeTargets.Property)]
public class LongStringAttribute : Attribute
{
}
二、新建一个类,用来处理添加NText类型参数;
public class LongString
{ public static void AddParameter(IDbCommand command, string name, string value)
{
var param = command.CreateParameter();
param.ParameterName = name;
param.Value = (object)value ?? DBNull.Value;
param.DbType = DbType.String; int length = -;
if (!string.IsNullOrEmpty(value))
length = value.Length;
if (length == - && value != null && value.Length <= )
{
param.Size = ;
}
else
{
param.Size = length;
} if (value != null)
{
if (length > && param.GetType().Name == "SqlCeParameter")
{
param.GetType().GetProperty("SqlDbType").SetValue(param, SqlDbType.NText, null);
param.Size = length;
}
} command.Parameters.Add(param);
} }
三、修改Dapper的源码,在SqlMapper.CreateParamInfoGenerator方法中,找到以下代码
if (prop.PropertyType == typeof(DbString))
{
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [typed-param]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [dbstring]
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [dbstring] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [dbstring] [command] [name]
il.EmitCall(OpCodes.Callvirt, typeof(DbString).GetMethod("AddParameter"), null); // stack is now [parameters]
continue;
} //我们的代码插入到这里 DbType dbType = LookupDbType(prop.PropertyType, prop.Name);
if (dbType == DbType.Xml)
{
// this actually represents special handling for list types;
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [command] [name]
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [command] [name] [typed-param]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [command] [name] [typed-value]
if (prop.PropertyType.IsValueType)
{
il.Emit(OpCodes.Box, prop.PropertyType); // stack is [parameters] [command] [name] [boxed-value]
}
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod("PackListParameters"), null); // stack is [parameters]
continue;
}
修改之后的代码如下:
if (prop.PropertyType == typeof(DbString))
{
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [typed-param]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [dbstring]
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [dbstring] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [dbstring] [command] [name]
il.EmitCall(OpCodes.Callvirt, typeof(DbString).GetMethod("AddParameter"), null); // stack is now [parameters]
continue;
} //这里插入修改的代码
Attribute lStrAttr = Attribute.GetCustomAttribute(prop, typeof(LongStringAttribute));
if (lStrAttr != null)
{
//special handling for long string
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [command] [name]
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [command] [name] [typed-param]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [command] [name] [string] il.EmitCall(OpCodes.Call, typeof(LongString).GetMethod("AddParameter"), null);
continue;
} DbType dbType = LookupDbType(prop.PropertyType, prop.Name);
if (dbType == DbType.Xml)
{
// this actually represents special handling for list types;
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [command] [name]
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [command] [name] [typed-param]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [command] [name] [typed-value]
if (prop.PropertyType.IsValueType)
{
il.Emit(OpCodes.Box, prop.PropertyType); // stack is [parameters] [command] [name] [boxed-value]
}
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod("PackListParameters"), null); // stack is [parameters]
continue;
}
这样就可以了,使用的时候,如果我们数据表的某字段是ntext类型,那么我们只需要在定义相应实体类的时候,给相应属性加上LongStringAttribute,Dapper就可以自动识别这个字段,插入正确的数据了。
使用代码如下:
//实体类定义
using System;
using Dapper; namespace Entity
{
public class product
{
public int Id { get; set; }
public int shopid { get; set; }
public string type { get; set; }
public string outid { get; set; }
public string link { get; set; }
public string title { get; set; }
[LongString]
public string content { get; set; }
public decimal price { get; set; }
public int amount { get; set; }
}
} //调用 product p = new product();
p.shopid = ;
p.title = "梁振英:\"占中\"者不要试探北京忍耐底线";
p.link = "http://news.163.com/14/1021/13/A936JGST0001124J.html";
string str = FileHelper.ReadTextFile("content.txt");
p.content = str;
p.type = "netease";
p.outid = "A936JGST0001124J";
p.price = 123.45M;
p.amount = ; SqlCeConnection conn = new SqlCeConnection("Data Source=test.sdf");
conn.Open(); string sql = "insert into products(shopid,type,outid,link,title,content,price,amount) values(@shopid,@type,@outid,@link,@title,@content,@price,@amount)";
SqlMapper.Execute(conn, sql, p); conn.Close();
我使用的Dapper版本是博客园里@wushilonng改写的针对.NET 2.0的版本,未知最新版Dapper是否针对这方面做了改进。
------全文完-----
让Dapper+SqlCE支持ntext数据类型和超过4000字符的存储的更多相关文章
- MongoDB 所支持的数据类型 创建和删除集合 创建和删除数据库
数据类型 MongoDB 支持如下数据类型: String:字符串.存储数据常用的数据类型.在 MongoDB 中,UTF-8 编码的字符串才是合法的. Integer:整型数值.用于存储数值.根据你 ...
- Sql Server 支持的数据类型
T-SQL语言和SQLServer数据库中的数据通常需要定义一个数据类型,数据类型定义了对象可以容纳的数据的种类. 哪些对象需要数据类型 (1).表和视图的列: 在定义 ...
- MySQL知识树-支持的数据类型
本篇学习笔记的主要内容: 介绍MySQL支持的各种数据类型(常用),并讲解其主要特点. MySQL支持多种数据类型,主要包括数值类型.日期和时间类型.字符串类型. 数值类型 MySQL的数值类型包 ...
- android sqlite支持的数据类型
Sqlite3支持的数据类型 :NULL.INTEGER.REAL.TEXT.BLOB 但实际上,sqlite3也接受如下的数据类型: smallint 16 位元的整数. interge ...
- mysql支持的数据类型及其测试
原文:mysql支持的数据类型及其测试 1.基础知识 1.1如何来查看mysql的帮助手册 ?int Help float; 1.2创建表的规则 CREATE TABLE [IF NOT EXISTS ...
- 初识Redis系列之三:Redis支持的数据类型及使用
支持的数据类型有五种: string(字符串).hash(哈希).list(列表).set(集合)及zset(sorted set:有序集合): 下面分别对这几种类型进行简单的Redis存取操作 1: ...
- 数据库 -- mysql支持的数据类型
mysql支持的数据类型 数值类型 MySQL支持所有标准SQL数值数据类型. 这些类型包括严格数值数据类型(INTEGER.SMALLINT.DECIMAL和NUMERIC),以及近似数值数据类型( ...
- 【SqlServer】Sql Server 支持的数据类型
在计算机中数据有两种特征:类型和长度.所谓数据类型就是以数据的表现方式和存储方式来划分的数据的种类. 在SQL Server 中每个变量.参数.表达式等都有数据类型.系统提供的数据类型分为几大类 ...
- 什么是redis?Reids的特点是什么?Redis支持的数据类型有哪些?
首先,分布式缓存框架 可以 看成是nosql的一种 (1)什么是redis? redis 是一个基于内存的高性能key-value数据库. (有空再补充,有理解错误或不足欢迎指正) (2)Reids的 ...
随机推荐
- Solr与HBase架构设计
摘要:本篇是本人在做一个大数据项目时,对于系统架构的一点总结,如何在保证存储量的情况下,又能保证数据的检索速度. 前提: Solr.SolrCloud提供了一整套的数据检索方案,HBase提 ...
- jQuery Validate 表单验证插件----自定义校验结果样式
一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW 访问密码 f224 二.引入依赖包 <script src="../../scripts/j ...
- Vrrp协议
一.简介 VRRP(Virtual Router Redundancy Protocol)协议是用于实现路由器冗余的协议,最新协议在RFC3768中定义,原来的定义RFC2338被废除,新协议相对还简 ...
- leetcode抽风的解决办法
添加hosts: 173.230.148.103 oj.leetcode.com173.230.148.103 leetcode.com
- 【温故而知新-Javascript】图片效果(图像震动效果、闪烁效果、自动切换图像)
1.当鼠标指针经过图像时图像震动效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- HTML5秘籍读书笔记
1:基本雏形 <html><head> <meta charset="UTF-8"> <title></title>&l ...
- 【转】${sessionScope.user}的使用方法
EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${ ...
- 传奇的通迅协议与base64算法
传奇的数据根本就没加密. 只要把#(数字)!去掉,中间的那些全部减0x3c,然后,四个字节一组,每个字节取低六位组成6*4=24位,然后分成3个字节,这个是很经典的base64的算法.不过小改了一些, ...
- 测试杂感:Bug Bash
缺陷大扫除(Bug Bash)是一项短期的全员测试活动.在微软,许多开发团队会在里程碑(milestone)的末期执行缺陷大扫除.程序员.测试员.程序经理.内部用户.市场人员在1~3天的时间窗口中,运 ...
- setAttribute改变属性,动态改变类
<style type="text/css"> .box{color:red;} </style> <div>通过setAttribute添加d ...