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。

该参数的具体含义可以参考http://msdn.microsoft.com/zh-cn/library/system.transactions.transactionscopeoption(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的时候才能算真正成功。

如果把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();
}
}

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

TransactionScopeOption的属性值:

对于多个不同服务器之间的数据库操作,TransactionScope依赖DTC(Distributed Transaction Coordinator)服务完成事务一致性。

但是对于单一服务器数据,TransactionScope的机制则比较复杂。主要用的的是线程静态特性。线程静态特性ThreadStaticAttribute让CLR知道,它标记的静态字段的存取是依赖当前线程,而独立于其他线程的。既然存储在线程静态字段中的数据只对存储该数据的同一线程中所运行的代码可见,那么,可使用此类字段将其他数据从一个方法传递到该第一个方法所调用的其他方法,而且完全不用担心其他线程会破坏它的工作。TransactionScope 会将当前的 Transaction 存储到线程静态字段中。当稍后实例化 SqlCommand 时(在此 TransactionScope 从线程局部存储中删除之前),该 SqlCommand 会检查线程静态字段以查找现有 Transaction,如果存在则列入该 Transaction 中。通过这种方式,TransactionScope 和 SqlCommand 能够协同工作,从而开发人员不必将 Transaction 显示传递给 SqlCommand 对象。实际上,TransactionScope 和 SqlCommand 所使用的机制非常复杂。

【转自】http://blog.csdn.net/wangxiaojia42121/article/details/53321625

最新文章

  1. JSON扩展类——JsonHelper
  2. ObjC运行时部分概念解析(二)
  3. 软件测试第二次作业——Fault,Failure,Error辨析与设计测试用例
  4. js-我理解的闭包
  5. 利用T4模板生成ASP.NET Core控制器的构造函数和参数
  6. 第二篇:基于K-近邻分类算法的约会对象智能匹配系统
  7. 【转】使用DateFormat把时间长度格式化为"时:分:秒"格式--不错
  8. web字体格式及几种在线格式转换工具介绍
  9. TASKKILL命令使用方法
  10. jquery动态刷新局部表单
  11. 题解 AT2390 【Games on DAG】
  12. Python-HTTP 概况
  13. linux安装redis标准流程-按这个来
  14. [网络流]Farm Tour(费用流
  15. Oracle中UNION和ORDER BY共用方法
  16. Android应用程序进程启动过程(后篇)
  17. XE 安装后C盘占用太大,C盘空间清理
  18. linux 中 ll 命令显示 的大小 是什么单位的啊?
  19. 20145202马超 2016-2017-2 《Java程序设计》第7周学习总结
  20. TF Boys (TensorFlow Boys ) 养成记(四):TensorFlow 简易 CIFAR10 分类网络

热门文章

  1. 解决php7.3 configure: error: off_t undefined
  2. jq:mouseover和mouseout多次触发解决办法
  3. python3--__call__拦截调用
  4. Leetcode 327.区间和的个数
  5. windows下在指定目录下打开命令行
  6. 【C#】堆、栈和堆栈的区别
  7. Mahout0.9安装与配置(完全分布式模式下运行)
  8. Codeforces Round #275 (Div. 2) B. Friends and Presents 二分+数学
  9. Redis命令行之String
  10. Spring Batch 文档(中文)