让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的 ...
随机推荐
- Windows环境下JDK安装与环境变量配置详细的图文教程
原文作者:souvc博文出处:http://www.cnblogs.com/liuhongfeng/p/4177568.html 本节内容:JDK安装与环境变量配置 以下是详细步骤 一.准备工具: 1 ...
- Eclipse 启动Tomcat 超时报错的解决方案
在用eclipse开发项目 用tomcat发布项目的时候 会提示超时, Server Tomcat v7.0 Server at localhost was unable to start wit ...
- find命令中参数perm的用法
按照文件权限模式用-perm选项,按文件权限模式来查找文件的话.最好使用八进制的权限表示法.如在当前目录下查找文件权限位为755的文件,即文件属主可以读.写.执行,其他用户可以读.执行的文件,可以用: ...
- 用Qemu模拟vexpress-a9 (四) --- u-boot引导kernel,用nfs挂载根文件系统
环境介绍 Win7 64 + Vmware 11 + ubuntu14.04 32 u-boot 版本:u-boot-2015-04 Linux kernel版本:linux-3.16.y busyb ...
- Azure CDN 启用HTTPS
默认情况下,订阅里的CDN不支持HTTPS 需要联系21v,提交工单告知订阅号,由后台为订阅启用CDN的HTTPS功能. 然后就可以在创建CDN时选到HTTPS的选项了.
- SSL certificate problem unable to get local issuer certificate解决办法
SSL certificate problem unable to get local issuer certificate 解决办法: 下载:ca-bundle.crt 将它放在自己的wamp或者x ...
- 按照索引的细化提取骨架算法的java实现
近期研究验证码识别,也就看了一些图像识别的资料,其中一种字体细化提取骨架的算法网上没有java版的实现,所以就选取了一个python实现版本进行java代码的改写.. python版实现的地址: ht ...
- iTOP-4412开发板低功耗高性能的开源硬件平台——上手评测
iTOP-4412开发板现在比较热门的开发板,笔者近期入了一套.也推荐给初学ARM的朋友学习,4412开发板搭载三星Exynos四核处理器,配备1GB内存,4GB固态硬盘EMMC存储,兼具快速读取与超 ...
- 关于hadoop 配置文件的一些实验
机器配置如下,两台机器,nn2,nn2,搭建基于QJM的高可用集群,zk集群. 如果我在yarn-site.xml中配置的nodemanager的可用资源过少,其他配置如果不一致,那么就会造成提交的j ...
- python Quicksort demo
__author__ = 'student' ''' quicksort step 1, choose one pivot, such as pivot=la[0] step 2, scan the ...