【转载】C#中回滚TransactionScope的使用要领和道理

时间:2022-05-11 07:36:00

标签:

TransactionScope只要一个操纵掉败,它会自动回滚,Complete暗示事务完成

实事上,一个错误的理解就是Complete()要领是提交事务的,这是错误的,事实上,它的感化的暗示本事务完成,它一般放在try{}的结尾处,不用判断前台操纵是否告成,如果弗成功,它会本身回滚。

在.net 1.1的时代,还没有TransactionScope类,因此很多关于事务的措置惩罚惩罚,都交给了SqlTransaction和SqlConnection,每个Transaction是基于每个Connection的。这种设计对付跨越多个措施集或者多个要领的事务行为来说,不长短常好,需要把事务和数据库连接作为参数传入。

在.net 2.0后,TransactionScope类的呈现,大大的简化了事务的设计。示例代码如下:

static void Main(string[] args) { using (TransactionScope ts = new TransactionScope()) { userBLL u = new userBLL(); TeacherBLL t = new TeacherBLL(); u.ADD(); t.ADD(); ts.Complete(); } }

只需要把需要事务包裹的逻辑块写在using (TransactionScope ts = new TransactionScope())中就可以了。从这种写法可以看出,TransactionScope实现了IDispose接口。除非显示挪用ts.Complete()要领。否则,系统不会自动提交这个事务。如果在代码运行退出这个block后,还未挪用Complete(),那么事务自动回滚了。在这个事务块中,u.ADD()要领和t.ADD()要领内部都没有用到任何事务类。

TransactionScope是基于当前线程的,在当前线程中,挪用Transaction.Current要领可以看到当前事务的信息。具体关于TransactionScope的使用要领,已经它的成员要领和属性,可以检察 MSDN 。

TransactionScope类是可以嵌套使用,如果要嵌套使用,需要在嵌套事务块中指定TransactionScopeOption参数。默认的这个参数为Required。

该参数的具体含义可以参考(v=vs.80).aspx

好比下面代码:

static void Main(string[] args) { using (TransactionScope ts = new TransactionScope()) { Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier); userBLL u = new userBLL(); TeacherBLL t = new TeacherBLL(); u.ADD(); using (TransactionScope ts2 = new TransactionScope(TransactionScopeOption.Required)) { Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier); t.ADD(); ts2.Complete(); } ts.Complete(); } }

当嵌套类的TransactionScope的TransactionScopeOption为Required的时候,则可以看到如下功效,他们的事务的ID都是同一个。并且,只有当2个TransactionScope都complete的时候才华算真正告成。

【转载】C#中回滚TransactionScope的使用要领和道理

如果把TransactionScopeOption设为RequiresNew,则嵌套的事务块和外层的事务块各自独立,互不影响。

static void Main(string[] args) { using (TransactionScope ts = new TransactionScope()) { Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier); userBLL u = new userBLL(); TeacherBLL t = new TeacherBLL(); u.ADD(); using (TransactionScope ts2 = new TransactionScope(TransactionScopeOption.RequiresNew)) { Console.WriteLine(Transaction.Current.TransactionInformation.LocalIdentifier); t.ADD(); ts2.Complete(); } ts.Complete(); } }

【转载】C#中回滚TransactionScope的使用要领和道理

可以看到,他们的事务id是不一样的。

TransactionScopeOption的属性值:

【转载】C#中回滚TransactionScope的使用要领和道理

对付多个差别处事器之间的数据库操纵,TransactionScope依赖DTC(Distributed Transaction Coordinator)处事完成事务一致性。

但是对付单一处事器数据,TransactionScope的机制则对照庞大。主要用的的是线程静态特性。线程静态特性ThreadStaticAttribute让CLR知道,它符号的静态字段的存取是依赖当前线程,而独立于其他线程的。既然存储在线程静态字段中的数据只对存储该数据的同一线程中所运行的代码可见,那么,可使用此类字段将其他数据从一个要领通报到该第一个要领所挪用的其他要领,而且完全不用担忧其他线程会粉碎它的事情。TransactionScope 会将当前的 Transaction 存储到线程静态字段中。当稍后实例化 SqlCommand 时(在此 TransactionScope 从线程局部存储中删除之前),,该 SqlCommand 会查抄线程静态字段以查找现有 Transaction,如果存在则列入该 Transaction 中。通过这种方法,TransactionScope 和 SqlCommand 能够协同事情,从而开发人员不必将 Transaction 显示通报给 SqlCommand 东西。实际上,TransactionScope 和 SqlCommand 所使用的机制非常庞大。