让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的 ...
随机推荐
- Gradle系列教程之依赖管理(转)
转自Lippi-浮生志 :http://ezlippi.com/blog/2015/05/gradle-dependency-management.html 这一章我将介绍Gradle对依赖管理的强大 ...
- Error during installing HAXM, VT-X not working 在安装HAXM错误,开始不工作
最佳答案 (Best Answer) Some antivirus options prevent Haxm installation. ie: Avast : settings (parametre ...
- MongoDB配置多个ConfigDB的问题(笔记)
由于在部署集群之前没有做好的规划,在集群中只有一个configserver和一个mongos.网上都推荐多个configserver,本人在使用的过程中发现在启动mongos进程时,congfigdb ...
- 分析递归式 Solving Recurrences------GeeksforGeeks 翻译
在上一章中我们讨论了如何分析循环语句.在现实中,有很多算法是递归的,当我们分析这些算法的时候我们要找到他们的的递归关系.例如归并排序,为了排序一个数组,我们把它平均分为两份然后再重复平分的步骤.最后我 ...
- nginx 一二事(1) - 简单图片服务器解决方案
最近经常有人问图片上传怎么做,有哪些方案做比较好,也看到过有关于上传图片的做法,但是都不是最好的 今天再这里简单讲一下上传图片以及图片服务器的大致理念 如果是个人项目或者企业小项目,仅仅只有十来号人使 ...
- LYK 快跑!(LYK别打我-)(话说LYK是谁)
LYK 快跑!(run) Time Limit:5000ms Memory Limit:64MB 题目描述 LYK 陷进了一个迷宫! 这个迷宫是网格图形状的. LYK 一开始在(1,1)位置, 出口在 ...
- 打包Android:Error building Player: CommandInvokationFailure
错误log Error building Player: CommandInvokationFailure: Unable to determine the tools version of the ...
- 2014Ember带来怎样的变化?
每隔几个月的时间,Ember的核心团队就会聚在一起讨论目前遇到的各种问题,并决定下一季度需要优先处理的各种事务. 这一次,在俄勒冈州的波特兰,大家聚在一起,商讨2014年的发展方向. 开发工具 &am ...
- 利用concat进行数组复制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Microsoft Visual Studio 下载转帖
1.VS2010 2.VS2012 Visual Studio 2012 Ultimate旗舰版序列号: YKCW6-BPFPF-BT8C9-7DCTH-QXGWC YQ7PR-QTHDM-HCBCV ...