关于使用Transaction对于非数据库事务的操作

在操作数据库的过程中,为了数据的一致性,我们可以使用Transaction,要么成功的时候全部提交,要么有任何一个操作失败立即全部回滚。不仅仅是在数据库方面,有时候操作其他的内容,比如说对于系统文件的操作,也需要把一些操作组合看做是一个事务。

 

现在我们看这样一个例子。现在我们需要在计算机的硬盘上创建3个目录A,B,C,要求要么3个全部创建成功,要么一个也不要创建。我们可以把这个看成是一个事务。如果我们自己写代码来操作,可以这样写。

 

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. bool createA = false;  
  2. bool createB = false;  
  3. bool createC = false;  
  4.   
  5. try  
  6. {  
  7.     //这里的操作是创建3个目录  
  8.     Directory.CreateDirectory("\\A");  
  9.     createA = true;  
  10.     Directory.CreateDirectory("\\B");  
  11.     createB = true;  
  12.     Directory.CreateDirectory("\\C");  
  13.     createC = true;  
  14. }  
  15. catch (System.Exception ex)  
  16. {  
  17.     //这里在捕捉到异常时,根据运行的结果进行回滚  
  18.     if (createB)  
  19.     {  
  20.         Directory.Delete("\\B");  
  21.         Directory.Delete("\\A");  
  22.     }  
  23.     if (!createB && createA)  
  24.     {  
  25.         Directory.Delete("\\A");  
  26.     }  
  27. }  



 

但是这里我们是把这3个操作当成一个整体来回滚,及时是简单的创建删除文件夹,我们可以看到catch中的回滚逻辑已经很复杂了。可以想象,如果A,B,C这3步不仅仅是创建目录,还有一些其他的操作,那么回滚的逻辑就非常复杂,此时,我们可以考虑把这一个分成几个小事务,分开回滚。代码可以这样写,这里我们使用了Framework提供的Transactin以及TransactioScope类。

 

[csharp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             //这里就不需要了try catch,因为scope就已经完成了这个功能,  
  6.             //即当有异常发生向外抛的时候,会尝试跳出这个using代码块,  
  7.             //CLR会在向代码块外边跑异常之前,分别取调用每个transaction的  
  8.             //roolback方法,只要rollback中你定义的逻辑没有问题,那么所有  
  9.             //的已发生的操作就会安全的回滚。  
  10.             using (var scope = new TransactionScope())  
  11.             {  
  12.                 var A = new OperationA();  
  13.                 Transaction.Current.EnlistVolatile(A, EnlistmentOptions.None);  
  14.                 A.DoWork();  
  15.   
  16.                 OperationB B = new OperationB();  
  17.                 Transaction.Current.EnlistVolatile(B, EnlistmentOptions.None);  
  18.                 B.DoWork();  
  19.                 scope.Complete();  
  20.             }  
  21.         }  
  22.   
  23.   
  24.     }  
  25. }  
  26.   
  27. class OperationA : IEnlistmentNotification  
  28. {  
  29.     private bool _isCommitSucceed = false;  
  30.   
  31.     public void Commit(Enlistment enlistment)  
  32.     {  
  33.         enlistment.Done();  
  34.     }  
  35.   
  36.     public void DoWork()//这是自定义的方法,不是继承IEnlistmentNotification  
  37.     {  
  38.         Directory.CreateDirectory("\\A");  
  39.         //这里还有一些其他的关于A的复杂操作  
  40.         _isCommitSucceed = true;  
  41.     }  
  42.   
  43.     public void InDoubt(Enlistment enlistment)  
  44.     {  
  45.         enlistment.Done();  
  46.     }  
  47.     public void Prepare(PreparingEnlistment preparingEnlistment)  
  48.     {  
  49.         preparingEnlistment.Prepared();  
  50.     }  
  51.     public void Rollback(Enlistment enlistment)  
  52.     {  
  53.         //这里回滚A的一些操作,当然这里的操作逻辑需要你自己来写。  
  54.         //比如说查看是否创建成功,或者有一些其他的信号标记,通过这些  
  55.         //标记你来决定是删除目录还是其他的什么回滚操作。  
  56.         if (_isCommitSucceed)  
  57.             Directory.Delete("\\A");  
  58.         enlistment.Done();  
  59.     }  
  60. }  
  61.   
  62. class OperationB : IEnlistmentNotification  
  63. {  
  64.     private bool _isCommitSucceed = false;  
  65.   
  66.     public void Commit(Enlistment enlistment)  
  67.     {  
  68.         enlistment.Done();  
  69.     }  
  70.   
  71.     public void DoWork()  
  72.     {  
  73.         //这里是关于B的一些复杂操作  
  74.         throw new Exception("test");  
  75.         //这里依然有一些操作代码,但是我们模拟的是B操作途中抛出异常,所以这里的代码不会执行  
  76.     }  
  77.   
  78.     public void InDoubt(Enlistment enlistment)  
  79.     {  
  80.         enlistment.Done();  
  81.     }  
  82.     public void Prepare(PreparingEnlistment preparingEnlistment)  
  83.     {  
  84.         preparingEnlistment.Prepared();  
  85.     }  
  86.     public void Rollback(Enlistment enlistment)  
  87.     {  
  88.         if (_isCommitSucceed)  
  89.         {  
  90.             //这里回滚B的一些已经存在的操作。  
  91.         }  
  92.         enlistment.Done();  
  93.     }  


这里的机制是这样的,可能是scope.Complete()方法中有某种特别的操作,去告诉CLR这次所有的操作都顺利完成了,在跳出这个scope的时候就不用调用那些transaction的rollback方法了。如果没有执行到scope.Complete()方法,那么就会在跳出这个scope代码块的时候调用rollback方法。一般造成这个的原因是在某个transaction的逻辑操作中出现异常,造成从此次直接抛出异常跳出这个代码块,没有机会执行下边的代码。可以看出这里的重点也是写rollback的逻辑,但是相对于原来的catch中的逻辑,这里分开为多个小的逻辑,相对来说容易了很多。

这只是个人写的一种使用回滚的逻辑。在使用IEnlistmentNotification的时候,也有人把业务逻辑写入到Commit中。如果想真正理解transaction回滚的机制,建议深入理解一下TransactionScope与Transactiond的实现机制。

转载于:https://www.cnblogs.com/sky6699/p/4535760.html

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

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

相关文章

php 判断修改成功,PHP判断文件是否被修改实例

在网站的管理系统中,有时需要查看某个文件是否被修改过、在什么时间被修改的、最后的修改时间是什么时候,本实例就可以实现这个功能,对表单中提交的文件进行判断,检测出修改时间。关键技术本实例主要应用filectime()和filemtime()…

nginx管理面板_吸塑包装自建网站上线,阿里云ecs+bt面板+WordPress

吸塑包装网站搭建是我经过对比了织梦dede、帝国和WordPress后选择了WordPress,从本地搭建的apache搬迁到阿里云ecs服务器。第一步,为了后期多网站的管理,安装了宝塔面板,做了域名解析。第二步,备份所有文件和数据库。在…

linux下c 编译脚本,Linux下编译C语言与makefile脚本语言

GCC1.Source CRT 软件:可以控制linux的终端。2.FileZilla 软件: windows 远程传文件到linux.使用sourceinsight 文本编辑器一linux编译过程:C语言编译器gcc 预处理指令-E ,汇编指令-s ,编译指令 -c , 链接指…

Teamwork(The sixth day of the team)

每日列会过后,我们的工作进度都有所进展了,好开心,但是还不是我们想要的,我们想做得更快,更好。 转载于:https://www.cnblogs.com/Lingchao/p/4535939.html

微软的平板电脑_Microsoft 微软 Surface Go 2 10.5英寸二合一平板电脑(m3-8100Y、8GB、128GB、LTE) 5788元...

Microsoft 微软 Surface Go 2 英寸二合一平板电脑(m3-8100Y、8GB、128GB、LTE)【PConline 聚超值】Surface Go 2是一款主打便携的二合一产品,外观上与上代产品相比,屏幕尺寸提升为英寸,屏幕分辨率从1800*1200 增加到 1920*1280,由…

linux刷命令脚本,linux – 如何调试bash脚本并获得每个命令的执行时间

这是尽可能接近内置bash调试工具的答案,因为它从脚本执行开始时间提供了整体时序信息.在脚本的顶部添加此项以进行第二次计数:export PS4[${SECONDS}s][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:${FUNCNAME[0]}(): }; set -x;相同,但用毫秒代替:Ndate …

指定查询条件,查询对应的集合List(单表)

TestDao.java(测试类) Test public void findCollectionByConditionNoPage(){ ApplicationContext ac new ClassPathXmlApplicationContext("beans.xml"); IElecTextService elecTextService (IElecTextService) ac.getBean(IElecTextServ…

PyCharm社区版支持深度学习_深度学习,大家都看哪些社区论坛?

对代码、编程感兴趣的可以加我公众号<老K玩代码>&#xff0c;和我交流!“学习Python&#xff0c;有一半的小伙伴是冲着深度学习来的。自学虽好&#xff0c;但还是需要有人指点。那有没有什么研究深度学习的朋友比较会聚集的网络社区或平台工具呢&#xff1f;其实是有的&a…

linux 自带 mysql,linux下安装mysql

1.查看CentOS自带的mysqlrpm -qa | grep mysql2.卸载CentOS自带的mysqlrpm -e --nodeps 要卸载的软件3.下载mysql.tar将mysql压缩包通过xftp连接到linux上4.上传mysql到linuxroot登录xshell5.在/usr/local/下创建mysql文件夹&#xff0c;解压Mysql到mysql目录cd /usr/localmkdi…

石油化工设备维护检修规程_旋回破碎机横梁臂架、衬板、内外铜套检修步骤及设备检修维护要点...

旋回破碎机做为常用的头破粗碎设备&#xff0c;其突出优势就是产能高&#xff0c;破碎比大&#xff0c;可达6-9.5&#xff0c;个别情况到13.5&#xff0c;且工作平稳&#xff0c;振动小。为了保障旋回破碎机在工作时保持良好的运行状态&#xff0c;必须要加强对其日常维护与检修…

《程序员开发心理学》阅读笔记一

今天开始阅读《程序员开发心理学》这本书&#xff0c;只是开了个小头。 这本书的开篇就提到了作者对于阅读程序的看法&#xff0c;正如老师交给我们的一样&#xff0c;在学习编程的时候第一步就是要学习&#xff0c;只有多看别的的程序、代码才有可能把它转化为自己的东西&…

摄像头图像分析目标物体大小位置_摄像头的原理、组成、选型及应用

目录一、摄像头成像的光学原理二、摄像头模组构成以及功能原理三、摄像头名词释义四、摄像头参数解析五、摄像头选型一、摄像头成像的光学原理1.1 光学的基本定律&#xff08;1&#xff09;光线直线传播定律&#xff1a;在统一均匀介质中&#xff0c;光沿直线传播&#xff08;2…

linux服务器上网页变形,Linux服务器上用iScanner删除网页恶意代码的方法

第一步&#xff1a;安装首先要确保服务器上已经安装了Ruby复制代码代码如下:#ruby -v //查看ruby的版本信息如果服务器上没有安装&#xff0c;可以通过yum或者apt-get安装ruby(根据自己服务器系统选择对应的方法安装)复制代码代码如下:#yum install ruby //centos用yum安装#apt…

切图总结

前些日子仿了优酷的首页&#xff0c;中间遇到一些问题&#xff0c;积累了点经验&#xff0c;做个总结。1. 需要最先明白的两点 不要只是无脑的切图&#xff0c;要去体会设计师的意图&#xff0c;不仅仅是还原设计稿&#xff0c;而且要尽可能去还原设计师的设计理念。切图的时候…

linux更改cxxflags环境变量,在64位的ubuntu 14.04 上开展32位Qt 程序开发环境配置(pro文件中增加 QMAKE_CXXFLAGS += -m32 命令)...

为了能中一个系统上开发64或32位C程序&#xff0c;费了些周折&#xff0c;现在终于能够开始干过了。在此记录此时针对Q5.4版本的32位开发环境配置过程。1. 下载Qt 5.4 的32位版本&#xff0c;进行安装&#xff0c;安装过程中会发现一些32位的库没有安装&#xff0c;根据提示的错…

git 合并冲突_GIT提交记录和Revert commit过程分析

一、根据GIT提交记录查看提交过程先做个git分支的背景介绍图1步骤说明1⃣️ 项目A 默认分支是 master2⃣️ 基于master分支创建 f1、f2、test分支3⃣️ f1 发起合并请求到 test分支4⃣️ f2 fetch & merge test分支 &#xff08;此时可能会有冲突&#xff09;5⃣️ &#x…

使用android-junit-report.jar导出单元测试报告

Android在使用脚本编译和测试时&#xff0c;使用默认的testrunner不会输出文件类型的单元测试报告&#xff0c;每次只能分析logcat的无法直观的看到单元测试结果和报告&#xff0c;这给编写自动化脚本带来了不少麻烦&#xff0c;虽然可以自己动手编写支持junit测试报告输出的Te…

2020.2idea创建web_使用IDEA配置Tomcat(亲测成功)

优质文章导读: XML入门(零基础教程) 一文了解Java反射 Servlet入门(零基础教程)配置环境变量打开环境变量设置,点击新建 新建两个变量CATALINA_HOME和CATELINA_BASE,变量值为Tomcat的安装路径 打开Path 添加进去刚刚创建的两个变量 IDEA中配置Tomcat创建web项目 点击 号 选择 …

linux打开另一台linux的图形化,【工具大道】ssh登录Linux服务器,并显示图形化界面...

点击关注微信公众号 "程序员的文娱情怀"分享提纲&#xff1a;1. 概述2. mac版实现ssh登录&#xff0c;显示图形化1. 概述平时ssh登录到Linux服务器都是在命令行下进行操作的&#xff0c;简单高效。但是有些时候&#xff0c;需要配置一些Linux系统下的图形化软件的参数…

c++循环执行一个函数_循环

循环目标程序的三大流程while 循环基本使用break 和 continuewhile 循环嵌套01. 程序的三大流程在程序开发中&#xff0c;一共有三种流程方式&#xff1a;顺序 —— 从上向下&#xff0c;顺序执行代码分支 —— 根据条件判断&#xff0c;决定执行代码的 分支循环 —— 让 特定代…