博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【网摘】C#中TransactionScope的使用方法和原理
阅读量:7082 次
发布时间:2019-06-28

本文共 3016 字,大约阅读时间需要 10 分钟。

 

在.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的使用方法,已经它的成员方法和属性,可以查看  。

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 所使用的机制非常复杂。具体可以参考文章

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

转载于:https://www.cnblogs.com/yscit/p/4897342.html

你可能感兴趣的文章
[面试∙网络] TCP/IP(四):TCP 与 UDP 协议简介
查看>>
浅谈 Objective-C Associated Objects
查看>>
编程或者软件开发到底算不算知识?
查看>>
iOS UI绘制原理
查看>>
JavaScript 二进制的 AST
查看>>
自定义控件(三) 源码分析measure流程
查看>>
不需要再手写 onSaveInstanceState 了,因为你的时间非常值钱
查看>>
SSL/TLS协议安全系列:CBC 模式的弱安全性介绍(一)
查看>>
几种通用防注入程序绕过方法
查看>>
Clickjacking简单介绍
查看>>
Android Tangram模型:手把手带你学习淘宝、天猫都在用的UI框架模型
查看>>
Android P 开发者预览版发布,细数开发者最不能错过的新特性
查看>>
SpringBoot使用JdbcTemplate
查看>>
flutter之从零开始搭建(三)之 网络请求
查看>>
AI开发者福音!阿里云推出国内首个基于英伟达NGC的GPU优化容器
查看>>
android中的用到的设计模式
查看>>
《JavaScript设计模式与开发实践》基础篇(1)—— this、call 和 apply
查看>>
Android TransactionTooLargeException 解析,思考与监控方案
查看>>
Android音频处理知识(一)MediaRecorder录制音频
查看>>
SpringBoot+Vue.js前后端分离实现大文件分块上传
查看>>