之前ORM比较火热,自己也搞了个WangSql,但是感觉比较low,大家都说Dapper性能好,所以现在学习学习Dapper,下面简单从宏观层面讲讲我学习的Dapper。

再了解一个东西前,先得学会使用,我也不再赘述怎么使用,接转一个文章吧

http://www.cnblogs.com/yankliu-vip/p/4182892.html

好就当学习了吧,该去看看源码了,到底怎么实现和好在哪呢。

先上一张图,已经把SqlMapper.cs按类拆分了,同时我自己在学习过程中也删了加了改了一些类。

当然最重要的类还是SqlMapper.cs这个类,那就开始吧。

本来想把这个SqlMapper.cs类代码全部粘贴的发现太长了,就算了吧,就把一些关键代码粘贴过来。

private static CacheInfo GetCacheInfo(Identity identity)

{

CacheInfo info;

if (!TryGetQueryCache(identity, out info))

{

info = new CacheInfo();

if (identity.parametersType != null)

{

if (typeof(string).IsAssignableFrom(identity.parametersType))

{

info.ParamReader = delegate(IDbCommand cmd, object obj) { (new StringParameters() as IDynamicParameters).AddParameters(cmd, identity, obj); };

}

else if (typeof(IDictionary).IsAssignableFrom(identity.parametersType))

{

info.ParamReader = delegate(IDbCommand cmd, object obj) { (new DictionaryParameters() as IDynamicParameters).AddParameters(cmd, identity, obj); };

}

else

{

info.ParamReader = CreateParamInfoGenerator(identity);

}

}

SetQueryCache(identity, info);

}

return info;

}

来来来,划重点了 info.ParamReader = CreateParamInfoGenerator(identity); 看到没,这货是干嘛的啊,哪里用的呢?

就这里用的,其实就是那是一个委托,主要用来创建Command的DataParameter的,不信看下面

private static IDbCommand SetupCommand(IDbConnection cnn, IDbTransaction transaction, string sql, Action<IDbCommand, object> paramReader, object obj, int? commandTimeout, CommandType? commandType)

{

var cmd = cnn.CreateCommand();

var bindByName = GetBindByName(cmd.GetType());

if (bindByName != null) bindByName(cmd, true);

cmd.Transaction = transaction;

cmd.CommandText = FormatSql(sql);

if (commandTimeout.HasValue)

cmd.CommandTimeout = commandTimeout.Value;

if (commandType.HasValue)

cmd.CommandType = commandType.Value;

if (paramReader != null)

{

paramReader(cmd, obj);

}

return cmd;

}

又划重点了, paramReader(cmd, obj); 这里就是执行委托创建Command的DataParameter了。

如果有人问为什么要这个呢,那就是你上面连Dapper基本使用都没看啊,滚回去看看先。

举个例子:

sql = "insert into Teacher(Id,Name) values(@Id,@Name)";

string tid = Guid.NewGuid().ToString();

teacher = new Teacher()

{

Id = tid,

Name = "wang"

};

intResult = SqlMapper.Execute(conn, sql, teacher);

这里 SqlMapper.Execute(conn, sql, teacher); 参数teacher就是上面 paramReader(cmd, obj);对应的参数obj,这个委托呢就是将自定义实体teacher变成cmd的Parameters。

那么你又要问了,怎么变的?额,这么嘛就是难点了....

回到上面看看,委托的创建 info.ParamReader = CreateParamInfoGenerator(identity);

关键点也是难点啊同学们CreateParamInfoGenerator这个方法是干嘛的啊,就是创建委托的啊,你个白痴。

好了,方法给你了,自己看吧,注释写的多详细的啊。恩....

WTF,英文的啊,不要紧有翻译的,反正自己看吧,我来给你讲怕误人子弟啊。

就我删减后的Dapper 来说入参解析部分其实就到此结束,什么鬼,毫无亮点,要你讲有何用。

别急,别急,下面讲讲我修改部分。

使用中,我发现参数的这么写 insert into Student(Id,Name,Tid) values(@Id,@Name,@Tid) 那如果我换了数据库比如MySql又得改@为?,换成Oracle又得把@改成:,这是我不能忍受的其一。

使用中,我发现 sql = "delete from Student where Id=#Id#"; intResult = SqlMapper.Execute(conn, sql, "jkajskajsk"); 报错,为毛啊,连字符串入参传入你都不认识,这是我不能忍受其二。

以上问题,可能是我版本问题,我用的是Dapper NET2.0版本。

不管为什么,先解决这个两个痛点。

问题一:

原因分析,主要是不知道数据库类型造成的。

解决办法,那我就提前告诉你,数据库相关信息,我们采用一种驱动方式来设置数据库相关信息。

我新建了个类DbProvider.cs

    internal class DbProvider{        public bool UseParameterPrefixInSql { get; set; }            public bool UseParameterPrefixInParameter { get; set; }              public string ParameterPrefix { get; set; }}

很简单,后期你可以自己扩展,  ParameterPrefix  这个就是数据库参数前缀,比如@ ? :

//dbProvider

dbProvider = new DbProvider()

{

UseParameterPrefixInSql = true,

UseParameterPrefixInParameter = true,

ParameterPrefix = "@"

};

在SqlMapper创建一个 dbProvider 构造函数里面 对其初始化,具体值最好写在web.config里面,初始化的时候去读配置文件。

有了这个之前的SQL我们可以改改了 insert into Student(Id,Name,Tid) values(#Id#,#Name#,#Tid#)当然原来的写法也是支持的,只不过现在这种写法,保证的SQL参数的统一性,以后切换数据库也容易多了。

可是这样写了,能正常运行吗?答案是NO,所以还需要下面的方法。

//我写的

internal static string FormatNameForSql(string parameterName)

{

return dbProvider.UseParameterPrefixInSql ? (dbProvider.ParameterPrefix + parameterName) : parameterName;

}

internal static string FormatNameForParameter(string parameterName)

{

return dbProvider.UseParameterPrefixInParameter ? (dbProvider.ParameterPrefix + parameterName) : parameterName;

}

internal static string FormatSql(string sql)

{

Regex regex = new Regex("#([a-zA-Z0-9_]+?)#", RegexOptions.IgnoreCase | RegexOptions.Multiline);

var ms = regex.Matches(sql);

foreach (Match item in ms)

{

sql = sql.Replace(item.Value, FormatNameForSql(item.Groups[1].Value));

}

return sql;

}

主要是这个方法 FormatSql 什么时候调呢,在这里

好了,问题一,反正是解决了,下面看看问题二了。

问题二:

原因分析,

来来来,划重点了 info.ParamReader = CreateParamInfoGenerator(identity); 看到没,这货是干嘛的啊,哪里用的呢?

就这里用的,其实就是那是一个委托,主要用来创建Command的DataParameter的

引用的上面的,那个委托啊CreateParamInfoGenerator不支持String、Dictionary这种入参造成的。

解决办法,既然那个委托不支持,我就给不同的类型创建不同的委托就行了啥。

我为继承string类型的创建了一个委托,委托是执行StringParameters实例的AddParameters方法。

我为继承IDictionary类型的创建了一个委托,委托是执行DictionaryParameters实例的AddParameters方法。

通过不同的委托就能实现不同入参实现给Command的Parameters创建赋值了,哈哈哈哈哈....当然你要实现int double ...都一样的方法,加个类继承IDynamicParameters即可。

现在这样子都可以正常使用了

sql = "delete from Student where Id=#Id#";

intResult = SqlMapper.Execute(conn, sql, "jkajskajsk");

sql = "delete from Student where Id=#Id# and Name=@Name and Name=@Name1";

Hashtable dic = new Hashtable();

dic.Add("Id", "123");

dic.Add("Name", "s1234");

dic.Add("Name1", "d12345");

intResult = SqlMapper.Execute(conn, sql, dic);

总结:

这篇文章只是对Dapper入参进行的分析,出参还没看呢,先这样吧,有空再说.

原文地址:http://www.cnblogs.com/deeround/p/6612213.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

Dapper源码学习和源码修改相关推荐

  1. Dapper源码学习和源码修改(下篇)

    继上篇Dapper源码学习和源码修改 讲了下自己学习Dapper的心得之后,下篇也随之而来,上篇主要讲的入参解析那下篇自然主打出参映射了. 好了,废话不多说,开始吧. 学习之前你的先学习怎么使用Dap ...

  2. Zxing生成二维码思路和源码解析

    Zxing生成二维码思路和源码解析 本博文是一篇介绍google zxing包生成二维码的思路和它的源码的文章. 一.引入 如何调用zxing的代码生成一个二维码呢?主要的函数只有一个,如下所示: B ...

  3. centos7下搭建lnmp环境包含yum源直接安装和源码编译安装,以及php5.3和php7.6版本

    LNMP环境的搭建 一.yum源直接搭建 1.安装epel源 2.安装mariadb 初始化mariadb 3.安装php模块 配置php-fpm 3.安装nginx 配置nginx 4.测试环境是否 ...

  4. jQuery1.3.2 源码学习 -1 $ 是什么?jQuery 又是什么?

    jQuery1.3.2  源码学习 本源码使用当前的 jQuery 1.3.2 版本,下载时间 2009-4-25,下载网站:jquery.com. 一个函数 1 /*! 2  * jQuery Ja ...

  5. ABP框架源码学习之修改默认数据库表前缀或表名称

    ABP框架源码学习之修改默认数据库表前缀或表名称 1,源码 1 namespace Abp.Zero.EntityFramework 2 { 3 /// <summary> 4 /// E ...

  6. 【原创】【专栏】《Linux设备驱动程序》--- LDD3源码目录结构和源码分析经典链接

    http://blog.csdn.net/geng823/article/details/37567557 [原创][专栏]<Linux设备驱动程序>--- LDD3源码目录结构和源码分析 ...

  7. 博通Broadcom SDK源码学习与开发12终结篇——TR069网管协议

    声明:原创作品,严禁用于商业目的. 本系列文章将全面剖析以Bcm33xxx芯片开发Cablemodem产品的SDK源码为例,从编译系统到各个功能模块进行分析与探讨. 文章目录 0.写在前篇 1. TR ...

  8. spring4.1.8初始化源码学习三部曲之三:AbstractApplicationContext.refresh方法

    本章是<spring4.1.8初始化源码学习三部曲>系列的终篇,重点是学习AbstractApplicationContext类的refresh()方法: 原文地址:https://blo ...

  9. jQuery源码学习之Callbacks

    jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...

最新文章

  1. 使用opencv中的merge()函数为BGR图像添加alpha通道
  2. 忍一时得寸进尺, 退一步变本加厉。
  3. HDU - 5877 Weak Pair (dfs序+树状数组+离散化)
  4. 前台MM手一抖,网络说抖它就抖!
  5. php 2个时间查询差几天,PHP怎么计算2个日期差
  6. canny算子 轮廓闭合_python实现:prewitt, laplace,sobel,scharr, canny, hed
  7. python入口文件详解_Python基础系列讲解——那些py文件中容易忽略的细节
  8. jstat 监控调整GC很好用
  9. 数据字典怎么写_做数据分析,我只会同环比,谁能教我怎么写结论?
  10. 清除计算机垃圾cmd命令,cmd清理垃圾命令代码是什么
  11. 【已解决】Win10系统点击ikbc机械键盘win键无效的解决方法
  12. Revit二次开发入门捷径_升维学习、降维打击
  13. 如何利用大数据软件进行家政服务的选址要素收集与分析
  14. 现代互联网的网络拓扑
  15. Excel如何快速提取图片地址位置?
  16. win10 系统出现“你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问。”
  17. #1082 : 然而沼跃鱼早就看穿了一切
  18. vue-router页面不渲染
  19. 什么软件能抠图换背景?这些软件大家都在用
  20. HC05蓝牙模块(一)

热门文章

  1. 【转】《从入门到精通云服务器》第六讲—OpenStack基础
  2. Emoji:搜索将与您找到表情符号背后的故事
  3. 深入分析Volatile的实现原理
  4. 解决scrollViewDidScroll do not work的方法
  5. 缓慢渐变维度的处理方式
  6. 关于MySQL 查询表数据大小的总结
  7. 九度 1376 最近零子序列
  8. 登陆xp系统,无法显示桌面
  9. proftpd的配置
  10. 只要300页!火遍全网的NET6+linux知识手册!拿走不谢!