在.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设为Suppress则为取消当前区块的事务,一般很少使用。

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

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

Wrox出版的《Professional C# 4 and .NET 4》也有关于TransactionScope的一些使用方法的介绍。

如果您觉得文章有用,也可以给水发个微信小额红包鼓励鼓励!!!

C#中TransactionScope的使用方法和原理相关推荐

  1. 【转载】C#中回滚TransactionScope的使用方法和原理

    TransactionScope只要一个操作失败,它会自动回滚,Complete表示事务完成 实事上,一个错误的理解就是Complete()方法是提交事务的,这是错误的,事实上,它的作用的表示本事务完 ...

  2. JavaScript中Object.prototype.toString方法的原理

    在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. <一>, ECMAScript 3  1. 在E ...

  3. C#中TransactionScope的使用小结

    --本篇文章主要是对C#中TransactionScope的使用方法进行了详细的介绍 TransactionScope是.Net Framework 2.0之后,新增了的一个名称空间.它的用途是为数据 ...

  4. MATLAB热障涂层成像,一种涡轮叶片热障涂层模拟试验过程中损伤实时检测方法与流程...

    本发明涉及航空发动机防护涂层技术领域,特别涉及一种涡轮叶片热障涂层模拟试验过程中损伤实时检测方法. 背景技术: 现代航空发动机已有两千多个部件应用有先进涂层材料,包括涡轮叶片.密封件.燃烧室密封件动件 ...

  5. Java中的深克隆和浅克隆的原理及三种方式实现深克隆

      本文详细介绍了Java中的浅克隆和深克隆的概念,及案例演示如何实现深克隆! 文章目录 1 克隆概述 2 深克隆实现 3 案例 3.1 测试普通clone方法--浅克隆 3.2 使用重写后的clon ...

  6. 继承实现的原理、子类中调用父类的方法、封装

    一.继承实现的原来 1.继承顺序 Python的类可以继承多个类.继承多个类的时候,其属性的寻找的方法有两种,分别是深度优先和广度优先. 如下的结构,新式类和经典类的属性查找顺序都一致.顺序为D--- ...

  7. 从0到1详解推荐系统中的嵌入方法,原理、算法到应用都讲明白了

    (图片由AI科技大本营付费下载自视觉中国) 作者丨gongyouliu 编辑丨lily 来源 | 大数据与人工智能(ID:) 前言 作者曾在这篇文章中提到,矩阵分解算法是一类嵌入方法,通过将用户行为矩 ...

  8. Day19:继承实现的原理、子类中调用父类的方法、封装

    一.继承实现的原来 1.继承顺序 Python的类可以继承多个类.继承多个类的时候,其属性的寻找的方法有两种,分别是深度优先和广度优先. 如下的结构,新式类和经典类的属性查找顺序都一致.顺序为D--- ...

  9. 深入理解Java中的反射机制和使用原理!详细解析invoke方法的执行和使用

    反射的概念 反射:Refelection,反射是Java的特征之一,允许运行中的Java程序获取自身信息,并可以操作类或者对象的内部属性 通过反射,可以在运行时获得程序或者程序中的每一个类型的成员活成 ...

最新文章

  1. Shuffle 相关
  2. hive金额怎么转换千位分隔符_金额字段加千位分隔符方法
  3. 2.Azure资源组迁移
  4. UWP通过机器学习加载ONNX进行表情识别
  5. 加密Spring加载的Properties文件
  6. 遇上DG挖矿病毒的处理记录
  7. 谷粒商城基础篇爬坑笔记--No Feign Client for loadBalancing defined以及加载测试失败
  8. LeetCode 515. 在每个树行中找最大值(广度优先搜索)
  9. ASP.NET实现简单的聊天室
  10. html 倒计时弹出框,alert警告框倒计时
  11. 【游戏测试】bug优先级的定义及如何描述
  12. web端调用高德API
  13. 【OpenCV】- 分水岭算法
  14. 谢谢 留下几个 那个有关于C++既QQ群吖
  15. iPhoneX、iPhoneXS、iPhoneXR、iPhoneXSMax屏幕适配尺寸@media
  16. 看完这篇文章你就可以告诉领导你精通Zookeeper了
  17. Scanvenger游戏制作笔记(三)Unity3D创建对墙体的攻击
  18. Windows Office 2019 很抱歉,此功能看似已中断,并需要修复
  19. Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'redis.maxIdle' in stri
  20. 小白从零开始在jetson nano上进行YOLOV3-Tiny 与 tensorrt加速检测

热门文章

  1. C++radix sort基数排序的实现算法之一(附完整源码)
  2. QT的QScxmlCppDataModel类的使用
  3. ubuntu 18 mysql5.7_Ubuntu18.04 下 MySQL5.7 的安装
  4. 画验证曲线_数学老师用“函数曲线”绘出美图 学生舍不得擦
  5. 通过源码的方式编译hadoop的安装文件
  6. mysql允许两个用户远程连接_mysql允许用户远程连接
  7. div 不受父级标签影响_前端H5开发中常用的标签
  8. centos 开机启动java_Centos 7将java jar包自定义开机启动服务
  9. PyTorch 实现 Mask-RCNN
  10. OpenTTD 1.9.0-beta3 发布,开源模拟经营游戏