.Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?
本文将通过场景例子演示,来通俗易懂的讲解在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码。
用一句话贯穿全文就是:通过委托来让TransactionScope的编码实现更直观,并不是讲述TransactionScope的其它如分布式、ACID等场景应用及解决方案。
通过一系列优化最终达到两个效果,1.让不了解TransactionScope的童鞋通过代码块TransactionScope来控制事务,2.让了解TransactionScope的童鞋简单概述本实例的委托思想抛砖引玉来优化TransactionScope的编码写法。
本文需要的知识点:1. Action委托 2. 分布式事务TransactionScope(不懂不要紧,文中会通过示例一和示例二简单讲解这是啥,为啥要用)
----------------------
.Net高级进阶,教你如何构建企业模型数据拦截层,动态控制字段验证
.Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?
web安全:通俗易懂,以实例讲述破解网站的原理及如何进行防护!如何让网站变得更安全。
.Net,Dll扫盲篇,如何在VS中调试已经编译好的dll?
----------------------
示例一和示例二,主要是来讲解 TransactionScope 是什么,为什么要用TransactionScope。
示例三(重要)则是优化写法,增加代码的灵活性和可读性。
【示例一】
现在,你要写个入库接口,大致意思就是: 勾选一条商品,然后写上数量,点击入库按钮,将会产生一条入库记录,同时 这个商品的所对应的 库存数量 也会 更新。
因为涉及到库存,所以要用事务来保证数据安全。
StorageTask:入库作业表,存写入库记录
GoodsInventory:商品库存表, 里面放的是 不同商品的 详细介绍、数量等信息
那么我们的实现 , 可能是 这样的 , 如图:

上图的代码,我们主要是先看 商品入库操作 GoodsInventoryOperate 这个Dal方法,放图:

上面的这是一个Dal方法,事务写法很大众,很常规,代码没毛病。
【示例二】
好,现在,我们的业务要求要改一下,改成这样的:
勾选了一条商品,输入该条商品的入库数量,然后又勾选了一条原材料,输入该原材料的入库数量,最终点击入库按钮,要 产生 商品的入库记录和原材料的入库记录, 还要 分别修改 所对应的 商品库存表和原材料库存表 的 库存数量
那么,我们就要修改下这个接口,首先,参数由原来的 单行的参数 改为 集合形式的 参数,

那么我们的接口代码也随之修改,如下图:

然后我们在看看 这个入库操作方法 InventoryOperate

我们来对比下,我们把之前的 商品入库操作 GoodsInventoryOperate 方法 给改成了 入库操作方法 InventoryOperate 。
实际上,入库操作方法 InventoryOperate = 商品入库操作 + 原材料入库操作 ,但是因为 业务的更改,让我们不得不把 原本 Dal层中的两个方法代码 给 复制粘贴到一起,形成第三个方法,也就是入库操作方法 InventoryOperate 。
那么,有没有一种写法,能让我们 更简单更方便 不用每次复制粘贴代码形式 来实现 事务的编写?
有!
TransactionScope:
在早期.net时代,如果想使用事务,就用SqlTransaction来实现,而每个SqlTransaction都会用同一个SqlConnection连接对象。
如果逻辑简单还好说,如果逻辑稍微复杂的话,想用多个Dal方法来共同组合一个事务的话,就非常费脑筋的,就像上文这样演变的 第一版 和 第二版。
为此,在.Net2.0时代,TransactionScope诞生了,微软官方描述:代码块事务,还有一个别称:分布式事务。
它实现了IDisposable接口,可以把它被实例化开始到被Dispose掉之间的代码作为一个事务,也就是它的存在,最终让你的代码块所嵌套在其中多个DAL方法变成“一个方法”
那么,当我们使用它以后,我们就可以这样编写:

【示例三】
现在,大家对 TransactionScope 有了基本的印象,那么现在考虑到代码的可读性和灵活性,我将要对当前风格再次改写,通过委托的形式让代码结构层次更加分明。
/// <summary>
/// 事务语句统一执行
/// </summary>
/// <param name="ac">委托</param>
/// <returns></returns>
public static bool TransactionExecute(Action ac)
{
try
{
using (TransactionScope ts = new TransactionScope())
{
ac.Invoke();
ts.Complete();
}
return true;
}
catch
{
return false;
}
}
然后,我们的接口方法的编码变成了这样:
/// <summary>
/// 商品仓库的入库作业操作
/// </summary>
/// <param name="iData">入库数据集合</param>
/// <returns></returns>
public string WarehouseGoodsOperate(List<InboundModel> iData)
{
Action ac = () => { };//声明一个委托
foreach (InboundModel item in iData)
{
if (item.type == "商品")
{
ac += () =>
{
IServices.Insert(item);
IServices.UpdateGoods(item);
};
}
if (item.type == "原材料")
{
ac += () =>
{
IServices.Insert(item);
IServices.UpdateInventory(item);
};
}
}
if (IServices.TransactionExecute(ac))
{
return "成功";
}
return "失败";
}
通过上面这样的写法,最终让代码风格更干净,同时在 事务的 处理上更灵活方便, 我们只需要把想要执行的 方法 让 ac 给包进去, 最后在调用 TransactionExecute 统一执行。
基于自己的场景可以定制自己的TransactionExecute,本文着重指出利用委托来优化该情况下的编码思想,至于TransactionExecute,这里只是做个简单的科普,其中有更多可挖掘的地方,感兴趣的童鞋可以自行百度。
当然,采用这种委托写法,需要注意一点:

因为传递的是引用,并且用用到了lambda,导致了闭包,最终在Invoke时在匿名类中会用同一引用。
那么,怎样解决这样情况?
逐个逐个的赋值,或者用反射?
不用,我们可以通过继承 ICloneable 接口,然后通过浅复制的方式实现Clone方法(浅复制拷贝时,string会创建新的实例,如果尚有除string之外的引用类型还需深拷贝)。
class SysUser : ICloneable
{
public object Clone()
{
return this.MemberwiseClone();
}
}
最后,我们就可以这样:

让正确的程序更快比让快速的程序正确要容易的多
我喜欢和我一样的人交朋友,不被环境影响,自己是自己的老师,欢迎加群 .Net web交流群, QQ群:166843154 欲望与挣扎
作者:小曾
出处:http://www.cnblogs.com/1996V/p/7798111.html 欢迎转载,但任何转载必须保留完整文章,在显要地方显示署名以及原文链接。如您有任何疑问或者授权方面的协商,请给我留言
.Net交流群, QQ群:166843154 欲望与挣扎

.Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?的更多相关文章
- (转).Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?
原文地址:http://www.cnblogs.com/1996V/p/7798111.html 示例一和示例二,主要是来讲解 TransactionScope 是什么,为什么要用Transactio ...
- DDD实战进阶第一波(八):开发一般业务的大健康行业直销系统(业务逻辑条件判断最佳实践)
这篇文章其实是大健康行业直销系统的番外篇,主要给大家讲讲如何在领域逻辑中,有效的处理业务逻辑条件判断的最佳实践问题. 大家都知道,聚合根.实体和值对象这些领域对象都自身处理自己的业务逻辑.在业务处理过 ...
- MyBatis知多少(6)表现层与业务逻辑层
表现层 表现层负责向最终用户展示应用程序的控制方式以及数据.它还要负责所有信息的布局和格式.今天,商业应用程序最流行的表现方式应该算是Web前端了,它使用HTML和JavaScript并通 过Web浏 ...
- 高级进阶DB2(第2版)——内部结构、高级管理与问题诊断
<高级进阶DB2(第2版)——内部结构.高级管理与问题诊断> 基本信息 作者: 牛新庄 出版社:清华大学出版社 ISBN:9787302323839 上架时间:2013-7-3 出版 ...
- .Net高级进阶,WebApi和MVC进行模型验证的时候,教你如何自由控制需要进行验证的字段?
现在,你有一个MVC架构的web项目,你要完成一个注册功能. 前台传了3个值到你的控制器,分别是账号.密码.邮箱. 如图:现在你要在控制器里面判断,账号名称.密码.邮箱不能为空,并且名称和密码不超过1 ...
- Odoo 12 开发手册指南(八)—— 业务逻辑 – 业务流程的支持
在前面的文章中,我们学习了模型层.如何创建应用数据结构以及如何使用 ORM API 来存储查看数据.本文中我们将利用前面所学的模型和记录集知识实现应用中常用的业务逻辑模式. 本文的主要内容有: 以文件 ...
- .Net高级进阶,教你如何构建企业模型数据拦截层,动态控制字段验证
现在,你有一个MVC架构的web项目,你要完成一个注册功能. 前台传了3个值到你的控制器,分别是账号.密码.邮箱. 如图:现在你要在控制器里面判断,账号名称.密码.邮箱不能为空,并且名称和密码不超过1 ...
- 高级进阶DB2(第2版)
<高级进阶DB2(第2版)> 基本信息 作者: 牛新庄 出版社:清华大学出版社 ISBN:9787302323839 上架时间:2013-7-3 出版日期:2013 年7月 开本:16开 ...
- Python高级进阶(一)Python框架之Django入门
传说中的Django Django由来 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的框架模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下 ...
随机推荐
- 【bzoj2761】[JLOI2011]不重复数字
给出N个数,要求把其中重复的去掉,只保留第一次出现的数. 例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4. Inpu ...
- bootstrap 的可编辑下拉框 jquery.editable-select
搜了半天发现在某处下载jquery.editable-select需要积分,于是整理出来方便 其他人. 先上下载链接:http://pan.baidu.com/s/1kUXvwlL pass ...
- mySQL使用实践
1.虚拟机安装mySQL 服务器, 宿主机分别使用navicat工具和java代码 访问mySQL,组网图如下: 2. 查看mySQL的服务器状态,如下: 3. 服务器上查看数据库和数据表内容如下: ...
- cocos2dx - 环境配置,项目创建
准备工具 cocos2dx当前最新版本:v3.9 官网下载地址: http://www.cocos.com/download/ python 2.7x最新版本:2.7.11 官 ...
- JavaScript设计模式--桥梁模式--XHR连接队列
针对该模式的例子现在不是很理解,写下来慢慢熟悉. 们要构建一个队列,队列里存放了很多ajax请求,使用队列(queue)主要是因为要确保先加入的请求先被处理.任何时候,我们可以暂停请求.删除请求.重试 ...
- Appium python自动化测试系列之appium环境搭建(二)
2.1 基础环境搭建 当我们学习新的一项技术开始基本都是从环境搭建开始,本书除了第一章节也是的,如果你连最基础的环境都没有那么我们也没必要去说太多,大概介绍一下: 1.因为appium是支持andr ...
- invalid types 'int[int]' for array subscript// EOF 输入多组数据//如何键盘输入EOF
数组维度搞错了 一次运行,要输入多组数据,直到读至输入文件末尾(EOF)为止 while(scanf("%d %d",&a, &b) != EOF) // 输入结束 ...
- win10 uwp 获得缩略图
有时候需要获得文件或视频的缩略图. 本文提供两个方法,用于获得文件的缩略图和截取视频指定时间的显示图片. 文件缩略图 如果有一个文件需要获得缩略图,可以使用 GetThumbnailAsync 或 G ...
- win10 UWP 隐式转换
implicit operator string <script type="text/javascript"> $(function () { $('pre.pret ...
- shell编程/字库裁剪(1)
我写这个帖子的意图,在于三个: 1.用代码生成代码的思维. 2.shell编程的思路. 3.裁剪字库的具体程序. 我打算分为三节来说: 第一节讲裁剪裁剪词库的意义以及使用场合: 第二节讲如何用shel ...