本文demo适用于MySQL

优点

高性能、易排查、易运维、灵活可控

缺点

和EF相比,手写sql当修改表结构不易发现bug。
习惯了EF后再来使用Dapper,会很难适应那种没有了强类型的安全感。不过可以用单元测和心细来避免。

问题:IDbConnection需不需要手动Open打开连接
答案:有时候需要有时候不需要

Dapper连接可分两种:主动管理(自己管理连接的打开和关闭)和自动管理(自动管理连接的打开和关闭)



bool wasClosed = cnn.State == ConnectionState.Closed;...if (wasClosed) cnn.Open();...if (wasClosed) cnn.Close();

源码位置 https://github.com/StackExchange/Dapper/blob/master/Dapper/SqlMapper.cs#L530

Note:ADO.NET默认是启用连接池的 Pooling = true,连接池中最大连接数,默认为100

在使用Dapper的过程中,你有可能遇到过连接池超过最大限制。那问题是怎么来的呢?
如果主动管理或者自动管理连接都不会有问题。就怕你管理一半,打开不关闭:

DBContext dBContext2 = new DBContext();dBContext2.DbConnection.Open();

解决办法相信不用我说了。

Note:在使用事务的时候需要手动打开连接,请不要忘记在catch里面Close。

批量新增

DbConnection.Execute(sqlStr, ListEntity);

insert into tt (a,b,c,d) values (50,1,'1','1'), (51,2,'1','2'); 

var sql = insert into tt (a,b,c,d) values (@a1,@b1,@c1,@d1), (@a2,@b2,@c2,@d2); DynamicParameters dynamicParameters = new DynamicParameters();dynamicParameters.Add("a1","value");dynamicParameters.Add("b1","value");dynamicParameters.Add("c1","value");dynamicParameters.Add("a2","value");dynamicParameters.Add("b2","value");dynamicParameters.Add("c2","value");dynamicParameters.Add("d2","value");DbConnection.ExecuteScalar<int>(sql, dynamicParameters)

批量修改

//1、可通过匿名对象集合进行参数化数据修改。(需要修改的值都不一样的情况下,性能优化参考4)DbConnection.Execute(sqlStr, ListEntity);//2、如果需要修改的值都是一样,只是条件不一样。(使用SQL语句中的IN语法)DbConnection.Execute("UPDATE tt SET aa = @aa where bb in @bb;", new { aa, bb }); //3、快速批量修改(此方法非常适合`新增或修改`数据的场景,可通过建联合唯一索引来实现新增或修改的区分。【组合字段不能为空,否则为空 不做唯一,有重复空数据】)insert into test_tbl (id,dr) values (1,'2'),(2,'3'),...(x,'y') on duplicate key update dr=values(dr);//4、参数化防sql注入var sql = insert into test_tbl (id,dr) values (@id1,@dr1),(@id2,@dr2),...(@idn,@drn) on duplicate key update dr=values(dr);DynamicParameters dynamicParameters = new DynamicParameters();dynamicParameters.Add("id1","value");dynamicParameters.Add("dr1","value");dynamicParameters.Add("id2","value");dynamicParameters.Add("dr2","value");...dynamicParameters.Add("idn","value");dynamicParameters.Add("drn","value");DbConnection.ExecuteScalar<int>(sql, dynamicParameters)

批量删除

同理,也可以使用参数化和IN语法

查询第一条数据

dBContext.DbConnection.QueryFirstOrDefault<ItemFCLPO>("SELECT * from itemfcl_temp limit 1;");    dBContext.DbConnection.QueryFirstOrDefault<ItemFCLPO>("SELECT * from itemfcl_temp;");            dBContext.DbConnection.Query<ItemFCLPO>("SELECT * from itemfcl_temp;").FirstOrDefault();         dBContext.DbConnection.Query<ItemFCLPO>("SELECT * from itemfcl_temp;").ToList().FirstOrDefault();

If扩展方法

使用过Mybatis的同学都知道,在xml里面写if、else还是蛮好用的。虽然我还是不喜欢在xml里面写sql。
那么在Dapper里面是不是也能简便操作,答案是肯定的。这就得庆幸C#牛逼的语法了。

public static class StringExtension{public static string If(this string str, bool condition){return condition ? str : string.Empty;    }} 

然后我们的sql就可以这样拼接了

left join MaintenanceTemplates it on it.Id = m.MaintenanceTemplateIdwhere m.IsDeleted = 0{" and m.Code = @KeyWord ".If(!string.IsNullOrWhiteSpace(input.KeyWord))}{" and m.ProjectId = @ProjectId ".If(input.ProjectId.HasValue)}{" and a.ProductId = @ProductId ".If(input.ProductId.HasValue)}

比起以前又臭又长的if判断,个人感觉好多了。

Note:Dapper不会因为传多了参数而报错,所以放心使用If。

使用EF的时候很方便做事务处理,而在Dapper中貌似就没那么优雅了。
我们每次在事务逻辑开始前都需要BeginTransaction开启,事务结束后都需要CommitTransaction提交。代码看起来也就稍显混乱。
如果我们通过特性标记的方式,在标记了UnitOfWork特性的方法自动开启和提交事务那就完美了。如下:

[UnitOfWork]public virtual void Test(){

}

当然,这是可行的。通过AOP拦截,在方法执行前开启事务,在方法执行后提交事务就可以了。
实现如下:
需要Nuget包Autofac.Extensions.DependencyInjection Autofac.Extras.DynamicProxy

[UnitOfWork]public virtual void DelUser(){var sql = "select * from UserTemp";var userList = dBContext.DbConnection.Query<object>(sql);

var sql2 = $@"INSERT into UserTemp VALUES(0,'{DateTime.Now.ToString()}','sql2执行成功')";    dBContext.DbConnection.Execute(sql2);throw new Exception("主动报错");

var sq3 = $@"INSERT into UserTemp VALUES(0,'{DateTime.Now.ToString()}','sq3执行成功')";    dBContext.DbConnection.Execute(sq3);}
public class UnitOfWorkIInterceptor : IInterceptor{private DBContext dBContext;public UnitOfWorkIInterceptor(DBContext dBContext){this.dBContext = dBContext;    }public void Intercept(IInvocation invocation){        MethodInfo methodInfo = invocation.MethodInvocationTarget;if (methodInfo == null)            methodInfo = invocation.Method;

        UnitOfWorkAttribute transaction = methodInfo.GetCustomAttributes<UnitOfWorkAttribute>(true).FirstOrDefault();

if (transaction != null && dBContext.Committed)        {

            dBContext.BeginTransaction();try            {

                invocation.Proceed();

                dBContext.CommitTransaction();            }catch (Exception ex)            {

                dBContext.RollBackTransaction();throw;            }        }else        {

            invocation.Proceed();        }    }}

完整的测试源码,会在文末提供。

使用EF的同学应该很多人都知道MiniProfiler,我在前些年分享EF的时候有做过简单介绍。
那么我们在执行Dapper的时候是不是也可以对生成的sql做检测和性能监控。
答案是肯定的。Git地址

MiniProfiler监控套件还真不是一般的强。EF、MongoDB、MySql、Redis、SqlServer统统支持。
接下来我们实现对Dapper监控,导入Nuget包MiniProfiler.AspNetCore

public class ActionFilter : IAsyncActionFilter{public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){var profiler = MiniProfiler.StartNew("StartNew");using (profiler.Step("Level1"))        {

await next();        }        WriteLog(profiler);    }    

private void WriteLog(MiniProfiler profiler){if (profiler?.Root != null)        {var root = profiler.Root;if (root.HasChildren)            {                root.Children.ForEach(chil =>                {if (chil.CustomTimings?.Count > 0)                    {foreach (var customTiming in chil.CustomTimings)                        {var all_sql = new List<string>();var err_sql = new List<string>();var all_log = new List<string>();int i = 1;                            customTiming.Value?.ForEach(value =>                            {if (value.ExecuteType != "OpenAsync")                                    all_sql.Add(value.CommandString);if (value.Errored)                                    err_sql.Add(value.CommandString);var log = $@"【{customTiming.Key}{i++}】{value.CommandString} Execute time :{value.DurationMilliseconds} ms,Start offset :{value.StartMilliseconds} ms,Errored :{value.Errored}";                                all_log.Add(log);                            });

                        }                    }                });            }        }    }}

运行效果:

完整的Demo源码:https://github.com/zhaopeiym/BlogDemoCode/tree/master/Dapper_Demo/DapperDemo

最后给大家推荐一个开源项目quartzui:https://github.com/zhaopeiym/quartzui
基于Quartz.NET 3.0的web管理界面,开箱即用。也可以完美运行在树莓派上。

docker run -v /fileData/quartzuifile:/app/File  --restart=unless-stopped --privileged=true --name quartzui -dp 5088:80 bennyzhao/quartzui:RaspberryPi  

运行在普通PC或云主机上

docker run -v /fileData/quartzuifile:/app/File  --restart=unless-stopped --privileged=true --name quartzui -dp 5088:80 bennyzhao/quartzui  

新建QQ群工控物联:995475200

原文地址:https://www.cnblogs.com/zhaopei/p/dapper.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

Dapper的正确使用姿势相关推荐

  1. 论机器学习的正确学习姿势

    论机器学习的正确学习姿势 策划 | 刘燕作者 | Caleb Kaiser翻译 | Sambodhi编辑 | Linda很多开发人员并没有机器学习领域的背景,在机器学习如火如荼的今天,没学过机器学习的 ...

  2. 什么叫取反_转载:CodeReview正确的姿势是什么?

    作者:微博是阿里孤尽 链接:https://www.zhihu.com/question/383079175/answer/1109655276 来源:知乎 著作权归作者所有.商业转载请联系作者获得授 ...

  3. class ts 扩展方法_ts类型声明文件的正确使用姿势

    ts类型声明文件的正确使用姿势 ts声明文件类型 npm install @types/jquery --save-dev 与npm一同发布 解释: package.json 中有 types 字段, ...

  4. java同步锁如何使用_java 同步锁(synchronized)的正确使用姿势

    关于线程安全,线程锁我们经常会用到,但你的使用姿势正确不,反正我用错了好长一段时间而不自知.所以有了这篇博客总结下线程锁的正确打开姿势 废话不说看例子 一,对整个方法进行加锁 1,对整个方法进行加锁, ...

  5. 直播预告|中台基石腾讯云TStack的正确使用姿势

    各位亲爱的小伙伴们,你们好啊~~ 他二哥技术直播又和大家见面了! 还记得在第一期的节目中,Sandy小姐姐和两位技术哥哥带我们见识了腾讯自研交换机的强大实力. (赶紧戳链接复习☝) 这次直播,他二哥邀 ...

  6. MongoDB系列:五、MongoDB Driver使用正确的姿势连接复制集

    MongoDB复制集(Replica Set)通过存储多份数据副本来保证数据的高可靠,通过自动的主备切换机制来保证服务的高可用.但需要注意的时,连接副本集的姿势如果不对,服务高可用将不复存在. 使用复 ...

  7. java 日志使用_Java日志正确使用姿势

    前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中"尽情"的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的 ...

  8. Python re 库的正确使用姿势

    前提假设: 已经充分掌握 PCRE 风格正则表达式 熟读 re 库文档 Why 正则表达式的强大已不用我赘述,Python 对此的支持也是十分强大,只不过: re.search(pattern, st ...

  9. 索引的正确“打开姿势”

    本文分享自华为云社区<DWS 索引的正确"打开姿势">,原文作者:hoholy . 索引能干什么呢,一言以蔽之:查询加速.常见的索引有下面几种: 1. 常用索引介绍 1 ...

最新文章

  1. 楚天高速拟12.6亿并购三木智能 涉足物联网领域
  2. 互联网引发全面深刻产业变革
  3. 对话百度贾磊/喻友平:深度学习正往跨领域融合高速发展
  4. 中小企业信息化--网页设计模拟题1
  5. 【CVPR Oral】TensorFlow实现StarGAN代码全部开源,1天训练完
  6. Springboot .properties或.yml配置文件读取pom.xml文件值
  7. springmvc与struts2的区别
  8. python import MySQLdb 解决报错 Error:Reason: image not found
  9. r语言 array c函数,R语言 数组
  10. SpriteBuilder改变布局后App运行出错代码排查
  11. 03day输入及转义符的使用
  12. Gprinter Android SDK V2.1 使用说明
  13. Java开发中常见的危险信号(中)
  14. 从感知机到Transformer,一文概述深度学习简史
  15. 【ES6】es6数组中对象去重,数组对象去重方法总结---filter()与reduce()实践
  16. ALSA应用层编程播放音乐
  17. AutoCAD Mechanical v2022.1.2 CAD机械版简体中文精简直装版
  18. windows服务ServiceProcess
  19. 小型计算机网络拓扑图,计算机网络课设——小型网络设计及实现.doc
  20. 网线线序如何排列,586B与586A的区别

热门文章

  1. java B2B2C Springcloud多租户电子商城系统-Spring Cloud Sleuth
  2. vue经验 - 细节小知识点汇总(更新中...)
  3. 老司机带你重构Android的v4包的部分源码
  4. oracle的本地安装和PUTTY+XMING远程连接安装和oracle翻页功能
  5. 记一次TCP连接异常故障解决
  6. 使用ABBYY FineReader进行自动图像预处理
  7. CMD、AMD、commonJs 规范的写法
  8. salt-ssh的使用(不需要安装客户端)
  9. linux centos7 root密码重置
  10. error LNK2001: unresolved external symbol public: __thiscall CNaDialog::CNaDialog(class CWnd *)