分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 软件开发

(转).Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?

发布时间:2023-09-06 01:24责任编辑:赖小花关键词:暂无标签

原文地址:http://www.cnblogs.com/1996V/p/7798111.html

示例一和示例二,主要是来讲解 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 有了基本的印象,那么现在考虑到代码的可读性和灵活性,我将要对当前风格再次改写,通过委托的形式让代码结构层次更加分明。

 1 ????????/// <summary> 2 ????????/// 事务语句统一执行 3 ????????/// </summary> 4 ????????/// <param name="ac">委托</param> 5 ????????/// <returns></returns> 6 ????????public static bool TransactionExecute(Action ac) 7 ????????{ 8 ????????????try 9 ????????????{10 ????????????????using (TransactionScope ts = new TransactionScope())11 ????????????????{12 ????????????????????ac.Invoke();13 ????????????????????ts.Complete();14 ????????????????}15 ????????????????return true;16 ????????????}17 ????????????catch18 ????????????{19 ????????????????return false;20 ????????????}21 ????????} ???

然后,我们的接口方法的编码变成了这样:

 1 ????????/// <summary> 2 ????????/// 商品仓库的入库作业操作 3 ????????/// </summary> 4 ????????/// <param name="iData">入库数据集合</param> 5 ????????/// <returns></returns> 6 ????????public string WarehouseGoodsOperate(List<InboundModel> iData) 7 ????????{ 8 ????????????Action ac = () => { };//声明一个委托 9 ????????????foreach (InboundModel item in iData)10 ????????????{11 ????????????????if (item.type == "商品")12 ????????????????{13 ????????????????????ac += () =>14 ????????????????????{15 ????????????????????????IServices.Insert(item);16 ????????????????????????IServices.UpdateGoods(item);17 ????????????????????};18 ????????????????}19 ????????????????if (item.type == "原材料")20 ????????????????{21 ????????????????????ac += () =>22 ????????????????????{23 ????????????????????????IServices.Insert(item);24 ????????????????????????IServices.UpdateInventory(item);25 ????????????????????};26 ????????????????}27 ????????????}28 ????????????if (IServices.TransactionExecute(ac))29 ????????????{30 ????????????????return "成功";31 ????????????}32 ????????????return "失败";33 ????????} 

 通过上面这样的写法,最终让代码风格更干净,同时在 事务的 处理上更灵活方便, 我们只需要把想要执行的 方法 让 ac 给包进去, 最后在调用 TransactionExecute 统一执行。

 基于自己的场景可以定制自己的TransactionExecute,本文着重指出利用委托来优化该情况下的编码思想,至于TransactionExecute,这里只是做个简单的科普,其中有更多可挖掘的地方,感兴趣的童鞋可以自行百度。

 当然,采用这种委托写法,需要注意一点:

因为 类 是 引用类型 ,传递的地址和值类型不同, 所以最终你的委托执行的是  你最后对实例的更改, 所以你认为的能行,实际上是不能行。

那么,怎样解决这样情况?
逐个逐个的赋值,或者用反射?
不用,我们可以通过继承 ICloneable 接口,然后通过浅复制的方式实现Clone方法。

 ???class SysUser : ICloneable ???{ ???????public object Clone() ???????{ ???????????return this.MemberwiseClone(); ????????} ???}

最后,我们就可以这样:

让正确的程序更快比让快速的程序正确要容易的多

(转).Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?

原文地址:http://www.cnblogs.com/hhhh2010/p/7818639.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved