关于使用Transaction对于非数据库事务的操作
在操作数据库的过程中,为了数据的一致性,我们可以使用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的实现机制。
关于使用Transaction对于非数据库事务的操作的更多相关文章
- mysql数据库事务的操作与理解
--------------------事务----------------------------------------------查询mysql事务隔离级别1.查看当前会话隔离级别select ...
- Mysql数据库事务的四大特性:
什么是事务? 事务Transaction,是指作为一个基本工作单元执行的一系列SQL语句的操作,要么完全地执行,要么完全地都不执行.为什么要使用事务:保证对数据操作的完整性和准确性.1,原子性:一个事 ...
- mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理
一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...
- transaction 数据库事务 roolback 回滚
事务是恢复和并发控制的基本单位 https://baike.baidu.com/item/数据库事务/9744607 事务有三种模型: 1.隐式事务是指每一条数据操作语句都自动地成为一个事务,事务的开 ...
- 【转】数据库事务ACID以及事务隔离
本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指 ...
- Django数据库--事务及事务回滚
数据库的读写操作中,事务在保证数据的安全性和一致性方面起着关键的作用,而回滚正是这里面的核心操作.Django的ORM在事务方面也提供了不少的API.有事务出错的整体回滚操作,也有基于保存点的部分回滚 ...
- 理解MySQL数据库事务
1. 什么是事务处理? 事务处理是一种机制,它是用来管理必须成批执行的mysql操作.来保证数据库不完整的操作结果. 2. 为什么要使用事务处理? 在使用mysql操作数据的过程中,如果只是简单的中小 ...
- 数据库事务的四大特性以及事务的隔离级别(mysql)
本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指 ...
- 数据库事务的四大特性以及事务的隔离级别-与-Spring事务传播机制&隔离级别
数据库事务的四大特性以及事务的隔离级别 本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ ...
随机推荐
- 【转】bzero, memset ,setmem 区别
原文网址:http://blog.csdn.net/agathe/article/details/6066157 bzero 原型: extern void bzero(void *s, int n ...
- LoopBar – Tap酒吧与无限滚动
相约 LoopBar – 标签栏与无限滚动为Android由Cleveroad 在Cleveroad我们最近认识到通过使用任何一个应用程序类别的导航,导航面板是很无聊和琐碎.这就是为什么我们的设计师的 ...
- Android studio gradle 打包 那些事
总结了一下 目前觉得比较好用的gradle 和一些打包 经验.放在这里. 首先说下 渠道号 这个概念,我们经常会统计我们的api 访问来源 是来自于那个app store,这有利于 我们针对性的推广. ...
- GreenDao官方文档翻译(下)
第五篇 查询 查询会返回符合某些特定标准的实体.你可以使用原始的SQL定制查询语句,或者更好的方式:使用GreenDao的QueryBuilder API.该查询也支持lazy-loading的结果集 ...
- C/C++中static关键字详解-zz
静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见.用法1:函数内部声明 ...
- redis介绍【转】
Redis新的存储模式diskstore Thursday, Jan 6th, 2011 by Tim | 13 CommentsFiled under: data | Tags: Mongo, Mo ...
- Android圆形图片--ImageView
[ RoundImageView.java ] package com.dxd.roundimageview; import android.content.Context; import andro ...
- 新的小游戏发布啦。Pop Jungle
丛林爱消除是一款画面清新,效果绚丽的消除类休闲游戏.你只需要选中尽可能多的图块,并消除它们就可以得到高分,并有无限多的关卡等待你去征服.一旦你开始玩儿你将无法停止下来,如果你还是消除星星的粉丝,那你更 ...
- 将cocos2dx项目从Visual Studio 迁移到 xcode
因为Visual Studio和XCode的巨大差异性,一开始选择任何一个IDE,都会有一个迁移的过程,XCode的迁移到Visual Studio相对非常简单,不用再介绍.将项目从Visual St ...
- 图的邻接表存储表示(C)
//---------图的邻接表存储表示------- #include<stdio.h> #include<stdlib.h> #define MAX_VERTEXT_NUM ...