高性能、易排查、易运维、灵活可控
和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。同理,也可以使用参数化和IN语法
使用过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