关于使用Transaction对于非数据库事务的操作
来源:互联网 发布:淘宝店铺装修教程2016 编辑:程序博客网 时间:2024/06/06 13:07
在操作数据库的过程中,为了数据的一致性,我们可以使用Transaction,要么成功的时候全部提交,要么有任何一个操作失败立即全部回滚。不仅仅是在数据库方面,有时候操作其他的内容,比如说对于系统文件的操作,也需要把一些操作组合看做是一个事务。
现在我们看这样一个例子。现在我们需要在计算机的硬盘上创建3个目录A,B,C,要求要么3个全部创建成功,要么一个也不要创建。我们可以把这个看成是一个事务。如果我们自己写代码来操作,可以这样写。
bool createA = false; bool createB = false; bool createC = false; try { //这里的操作是创建3个目录 Directory.CreateDirectory("\\A"); createA = true; Directory.CreateDirectory("\\B"); createB = true; Directory.CreateDirectory("\\C"); createC = true; } catch (System.Exception ex) { //这里在捕捉到异常时,根据运行的结果进行回滚 if (createB) { Directory.Delete("\\B"); Directory.Delete("\\A"); } if (!createB && createA) { Directory.Delete("\\A"); } }
但是这里我们是把这3个操作当成一个整体来回滚,及时是简单的创建删除文件夹,我们可以看到catch中的回滚逻辑已经很复杂了。可以想象,如果A,B,C这3步不仅仅是创建目录,还有一些其他的操作,那么回滚的逻辑就非常复杂,此时,我们可以考虑把这一个分成几个小事务,分开回滚。代码可以这样写,这里我们使用了Framework提供的Transactin以及TransactioScope类。
class Program { static void Main(string[] args) { //这里就不需要了try catch,因为scope就已经完成了这个功能, //即当有异常发生向外抛的时候,会尝试跳出这个using代码块, //CLR会在向代码块外边跑异常之前,分别取调用每个transaction的 //roolback方法,只要rollback中你定义的逻辑没有问题,那么所有 //的已发生的操作就会安全的回滚。 using (var scope = new TransactionScope()) { var A = new OperationA(); Transaction.Current.EnlistVolatile(A, EnlistmentOptions.None); A.DoWork(); OperationB B = new OperationB(); Transaction.Current.EnlistVolatile(B, EnlistmentOptions.None); B.DoWork(); scope.Complete(); } } }}class OperationA : IEnlistmentNotification{ private bool _isCommitSucceed = false; public void Commit(Enlistment enlistment) { enlistment.Done(); } public void DoWork()//这是自定义的方法,不是继承IEnlistmentNotification { Directory.CreateDirectory("\\A"); //这里还有一些其他的关于A的复杂操作 _isCommitSucceed = true; } public void InDoubt(Enlistment enlistment) { enlistment.Done(); } public void Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); } public void Rollback(Enlistment enlistment) { //这里回滚A的一些操作,当然这里的操作逻辑需要你自己来写。 //比如说查看是否创建成功,或者有一些其他的信号标记,通过这些 //标记你来决定是删除目录还是其他的什么回滚操作。 if (_isCommitSucceed) Directory.Delete("\\A"); enlistment.Done(); }}class OperationB : IEnlistmentNotification{ private bool _isCommitSucceed = false; public void Commit(Enlistment enlistment) { enlistment.Done(); } public void DoWork() { //这里是关于B的一些复杂操作 throw new Exception("test"); //这里依然有一些操作代码,但是我们模拟的是B操作途中抛出异常,所以这里的代码不会执行 } public void InDoubt(Enlistment enlistment) { enlistment.Done(); } public void Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); } public void Rollback(Enlistment enlistment) { if (_isCommitSucceed) { //这里回滚B的一些已经存在的操作。 } enlistment.Done(); }
这里的机制是这样的,可能是scope.Complete()方法中有某种特别的操作,去告诉CLR这次所有的操作都顺利完成了,在跳出这个scope的时候就不用调用那些transaction的rollback方法了。如果没有执行到scope.Complete()方法,那么就会在跳出这个scope代码块的时候调用rollback方法。一般造成这个的原因是在某个transaction的逻辑操作中出现异常,造成从此次直接抛出异常跳出这个代码块,没有机会执行下边的代码。可以看出这里的重点也是写rollback的逻辑,但是相对于原来的catch中的逻辑,这里分开为多个小的逻辑,相对来说容易了很多。
这只是个人写的一种使用回滚的逻辑。在使用IEnlistmentNotification的时候,也有人把业务逻辑写入到Commit中。如果想真正理解transaction回滚的机制,建议深入理解一下TransactionScope与Transactiond的实现机制。
0 0
- 关于使用Transaction对于非数据库事务的操作
- 关于数据库操作的事务
- 数据库的事务(transaction)
- 关于数据库操作及事务的处理
- 数据库事务(Transaction)的ACID特性解释
- 数据库事务(Transaction)的ACID特性解释
- 关于Transaction事务的那点事
- 关于事务(Transaction)的几个概念
- sqlite transaction事务操作
- 数据库事务(TRANSACTION)
- 数据库事务 - Transaction
- 数据库--事务Transaction
- 数据库事务 - Transaction
- 数据库事务TRANSACTION
- “数据库事务(Database Transaction)
- 关于事务(transaction)
- 关于数据库中的事务(transaction),程序员必须记住的三点
- redis中事务(Transaction)的使用
- Poi拷贝Excel Sheet(解决合并单元格计数问题)
- 2014 百度笔试 机器学习及数据挖掘
- JavaWeb入门经典实例
- KMP算法
- OCP 1Z0 052 122
- 关于使用Transaction对于非数据库事务的操作
- 设计模式——适配器模式
- POI导出Exel表中图片到文件夹下
- CSDN 夏令营程序 试题分析 (3)
- nginx安装及启动
- poi获取Excel表中图片位置
- 修改MyEclipse行数的颜色
- spring mina整合(客户端进行调用)
- SQL语句集锦——数据库表查询、更新、删除等SQL语法