用了Dapper之后通篇还是SqlConnection,真的看不下去了

一:背景

1. 讲故事

前几天看公司一个新项目的底层使用了dapper,大家都知道dapper是一个非常强大的半自动化orm,帮程序员解决了繁琐的mapping问题,用起来非常爽,但我还是遇到了一件非常不爽的事情,如下代码所示:

public class UserDAL : BaseDAL{public List<UserModel> GetList(){using (SqlConnection conn = new SqlConnection(ConnectionString)){var list = conn.Query<UserModel>("select * from users").ToList();return list;}}public bool Insert(){using (SqlConnection conn = new SqlConnection(ConnectionString)){var execnum = conn.Execute("insert into xxx ");return execnum > 0;}}public bool Update(){using (SqlConnection conn = new SqlConnection(ConnectionString)){var execnum = conn.Execute("update xxx ....");return execnum > 0;}}}public class UserModel {}

扫一下代码是不是总感觉哪里不对劲,是的,为了能使用上Dapper的扩展方法,这里面每个方法中都配上了模板化的 using (SqlConnection conn = new SqlConnection(ConnectionString)),虽然这样写逻辑上没有任何问题,但我有洁癖哈,接下来试着封装一下,嘿嘿,用更少的代码做更多的事情。

二:模板化代码封装探索

1. 将模板化的代码提取到父类中

仔细看上面的模板代码你会发现,真正的业务逻辑是写在 using 中的,而该块中只需要拿到一个 conn 就可以了,其他的统一提取封装到父类中,这就可以用到 委托函数啦,对不对,用这个思路代码修改如下:

public class BaseDAL{protected string ConnectionString { get; set; }public T Execute<T>(Func<SqlConnection, T> func){using (SqlConnection connection = new SqlConnection(ConnectionString)){return func(connection);}}}

有了父类通用的 Execute 方法,接下来子类中就可以直接用它啦,改造如下:

public class UserDAL : BaseDAL{public List<UserModel> GetList(){return Execute((conn) =>{var list = conn.Query<UserModel>("select * from users").ToList();return list;});}public bool Insert(){return Execute((conn) =>{var execnum = conn.Execute("insert into xxx ");return execnum > 0;});}public bool Update(){return Execute((conn) =>{var execnum = conn.Execute("update xxx ....");return execnum > 0;});}}

改造之后代码是不是清晰多了,仅仅这一个通用方法貌似还不行,起码 ConnectionString 不能框死。

2. 增加ConnectionString 入口参数

相信有不少朋友的公司是做 ToB 的业务,一般是一个商家一个DB的设计思路,这里就需要在 Execute 上增加一个 ConnectionString 字符串参数,你可以通过重载方法 或者 可选参数,改造如下:

        public T Execute<T>(Func<SqlConnection, T> func){return Execute(ConnectionString, func);}public T Execute<T>(string connectionString, Func<SqlConnection, T> func){using (SqlConnection connection = new SqlConnection(connectionString ?? ConnectionString)){return func(connection);}}public class UserDAL : BaseDAL{public List<UserModel> GetList(string connectionString){return Execute(connectionString, (conn) =>{var list = conn.Query<UserModel>("select * from users").ToList();return list;});}}

这样看起来就舒服多了,不过还有一个问题,我们的程序是给客户独立部署的,越简单越好,否则实施人员会砍人的,所以很多用户操作和api轨迹行为都记录到了sqlserver中,这里就有一个 业务表 和 一个 事务日志表,而且要作为原子化提交,这里就涉及到了事务操作。

2. 支持事务操作

因为有同时插入两张表的业务逻辑,免不了使用 transaction,接下来继续扩展 Execute 方法,代码如下:

public T Execute<T>(Func<SqlConnection, SqlTransaction, T> func){return Execute(ConnectionString, func);}public T Execute<T>(string connectionString, Func<SqlConnection, SqlTransaction, T> func){using (SqlConnection connection = new SqlConnection(connectionString ?? ConnectionString)){connection.Open();using (var transaction = connection.BeginTransaction()){return func(connection, transaction);}}}

上面的代码应该很好理解,将 transaction 作为回调函数的参数,业务逻辑部分直接将 transaction 塞入到各自的业务代码中即可,子类可以改造如下:

public bool Insert(){return Execute((conn, trans) =>{var execnum = conn.Execute("insert into xxx ", transaction: trans);if (execnum == 0) return false;var execnum2 = conn.Execute("update xxx set xxx", transaction: trans);if (execnum2 > 0) trans.Commit();return execnum > 0;});}

这样 Execute 对 transaction 的支持貌似也差不多了,异步版的我就不在此封装啦。

四:总结

文章来源于工作中的点点滴滴,这也是我的即兴封装,大家要是有更好的封装代码,欢迎交流,独乐乐不如众乐乐,本篇就说到这里啦,希望对您有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308427.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java swing 控件拖动_java swing中实现拖拽功能示例

java实现拖拽示例Swing中实现拖拽功能&#xff0c;代码很简单&#xff0c;都有注释&#xff0c;自己看&#xff0c;运行效果如下图&#xff1a;package com;import java.awt.*;import java.awt.datatransfer.DataFlavor;import java.awt.dnd.DnDConstants;import java.awt.dnd.…

7-26 Windows消息队列 (25 分)(详解+思路+超时解决)

一&#xff1a;题目 消息队列是Windows系统的基础。对于每个进程&#xff0c;系统维护一个消息队列。如果在进程中有特定事件发生&#xff0c;如点击鼠标、文字改变等&#xff0c;系统将把这个消息加到队列当中。同时&#xff0c;如果队列不是空的&#xff0c;这一进程循环地从…

一文说通C#中的异步编程补遗

前文写了关于C#中的异步编程。后台有无数人在讨论&#xff0c;很多人把异步和多线程混了。文章在这儿&#xff1a;一文说通C#中的异步编程所以&#xff0c;本文从体系的角度&#xff0c;再写一下这个异步编程。一、C#中的异步编程演变1. 异步编程模型这是C#中早期的异步模型&am…

java 视频监控 分屏ui_视频监控网页ActiveX视频分屏播放控件开发

最近在搞视频监控项目&#xff0c;需要在网页上显示实时视频&#xff0c;于是网上找了很多资料研究如何在网页上播放视频&#xff0c;一种实现方式就是开发activex控件嵌入到网页中。如下我将介绍如何开发一个可以分屏播放视频的activex控件 (部分内容也是从网上抄的&#xff0…

Java当中 文件得输入流 输出流

一&#xff1a;引言 InputStream 和 OutputStream 两个抽象类&#xff0c;我们主要用其实现类来操作 二&#xff1a;InputStream 输入流&#xff0c;从文件当中读数据到程序当中&#xff0c;我们要站在程序得角度上。 package com.wyj.two;import java.io.File; import jav…

基于.NetCore3.1系列 —— 日志记录之日志核心要素揭秘

前言在上一篇中&#xff0c;我们已经了解了内置系统的默认配置和自定义配置的方式&#xff0c;在学习了配置的基础上&#xff0c;我们进一步的对日志在程序中是如何使用的深入了解学习。所以在这一篇中&#xff0c;主要是对日志记录的核心机制进行学习说明。说明在上一篇中&…

array remove java_how to remove array from another array in javascript

可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:问题:0: {id: 1553825061863, name: "Thai Milk Tea", qty: "1", total_amount: 9500, toppings: 500, …}1: {id: 1553825061863, name: "Thai Milk Tea", qty: "1", total_a…

Java 文件的拷贝

一&#xff1a;上码 package com.wyj.two;import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;/*** 文件…

listview在java中的使用_我的Android开发之路——ListView的使用

在Android开发过程中&#xff0c;遇到需要列表显示的时候&#xff0c;这时候就会用到listview。1.首先创建一个ListViewTest项目&#xff0c;选择empty activity类型。修改activity_main.xml的布局文件&#xff0c;添加listview控件&#xff0c;设置宽高和id等属性此时通过预览…

如何利用NLog输出结构化日志,并在Kibana优雅分析日志?

上文我们演示了使用NLog向ElasticSearch写日志的基本过程(输出的是普通文本日志)&#xff0c;今天我们来看下如何向ES输出结构化日志、在Kibana中分析日志。什么是结构化日志&#xff1f;当前互联网、物联网、大数据突飞猛进&#xff0c;软件越复杂&#xff0c;查找任何给定问题…

C++中字符串的截取 str.substr(a,b);

C中字符串的截取 str.substr(a,b); #include<bits/stdc.h> using namespace std;int main() {//str.substr(a,b);a表示截取字符串的下标&#xff0c;b表示要截取的长度不填则为截取的到最后 string str "aaaabc";cout << str.substr(3) << endl;…

java打印设备集中管理_Kafka+Log4j实现日志集中管理

记录如何使用KafkaLog4j实现集中日志管理的过程。引言前面写的《SpringLog4jActiveMQ实现远程记录日志——实战分析》得到了许多同学的认可&#xff0c;在认可的同时&#xff0c;也有同学提出可以使用Kafka来集中管理日志&#xff0c;于是今天就来学习一下。特别说明&#xff0…

7-27 家谱处理 (30 分)(详解+map做法)map真香啊

一&#xff1a;题目 人类学研究对于家族很感兴趣&#xff0c;于是研究人员搜集了一些家族的家谱进行研究。实验中&#xff0c;使用计算机处理家谱。为了实现这个目的&#xff0c;研究人员将家谱转换为文本文件。下面为家谱文本文件的实例&#xff1a; John Robert Frank Andr…

微软开源基于 Envoy 的服务网格 Open Service Mesh

原文地址&#xff1a;https://techcrunch.com/2020/08/05/microsoft-launches-open-service-mesh/Open Service Mesh&#xff08;OSM&#xff09;是一个轻量级的、可扩展的、云原生的服务网格&#xff0c;它允许用户对高度动态的微服务环境进行统一管理、安全保护&#xff0c;并…

java servlet jsp javabean关系图_Servlet+JSP+JavaBean开发模式(MVC)介绍

好伤心...写登陆注册之前看见一篇很好的博文&#xff0c;没有收藏&#xff0c;然后找不到了。前几天在知乎上看见一个问题&#xff0c;什么时候感觉最无力。前两天一直想回答&#xff1a;尝试过google到的所有solve case&#xff0c;结果bug依然在。今天想回答&#xff1a;明明…

7-28 搜索树判断 (25 分)(思路加详解) just easy!

一&#xff1a;题目 对于二叉搜索树&#xff0c;我们规定任一结点的左子树仅包含严格小于该结点的键值&#xff0c;而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树&#xff0c;得到的树叫做镜像二叉搜索树。 现在我们给出一个整数键值序列&…

Azure DevOps+Docker+Asp.NET Core 实现CI/CD(一 .简介与创建自己的代理池)

前言本文主要是讲解如何使用Azure DevOpsDocker 来实现持续集成Asp.NET Core项目(当然 也可以是任意项目).打算用三个篇幅来记录完整的全过程觉得有帮助的朋友~可以左上角点个关注,右下角点个推荐CI/CD简介首先,我们先来简单的介绍一下什么是CI/CDCI全拼Continuous Integration…

7-31 笛卡尔树(25分)(题目分析+简单算法+详解+思路)

一&#xff1a;题目 7-31 笛卡尔树 (25 分) 笛卡尔树是一种特殊的二叉树&#xff0c;其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树&#xff0c;即结点左子树的所有K1值都比该结点的K1值小&#xff0c;右子树则大。其次所有结点的K2关键字满足优先队列&#…

java ee导入后乱码_JavaEE中为什么出现中文乱码?

1.原因客户端通过IE提交时用的默认编码是UTF-8&#xff0c;而当我们用Myeclipse的时候的服务端接受的时候用的是iso-8859-12.解决方法服务端也用UTF-8编码byte[] result request.getParameter("titile").getBytes("iso-8859-1") ;title new String(resu…

Java多线程之龟兔赛跑和抢票

一&#xff1a;引言 练习这个码主要是为了体验在实现 多线程的方式中 实现Runable接口的好处&#xff0c;其中之一 有共享资源 &#xff0c;一个实现类但可以有多个代理 二&#xff1a;龟兔赛跑 package com.wyj.one; /*** 实现Runable接口也就是可以共享资源* author 86155…