【网摘】C#中TransactionScope的使用方法和原理

时间 2013-08-12 19:59:34  51CTO推荐博文

原文  http://cnn237111.blog.51cto.com/2359144/1271600

在.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的一些使用方法的介绍。

时间: 2024-08-01 11:40:42

【网摘】C#中TransactionScope的使用方法和原理的相关文章

C#中TransactionScope的使用方法和原理(摘)

出自51CTO博客:http://cnn237111.blog.51cto.com/2359144/1271600 在.net 1.1的时代,还没有TransactionScope类,因此很多关于事务的处理,都交给了SqlTransaction和 SqlConnection,每个Transaction是基于每个Connection的.这种设计对于跨越多个程序集或者多个方法的事务行为来说,不 是非常好,需要把事务和数据库连接作为参数传入. 在.net 2.0后,TransactionScope类的

C#中TransactionScope的使用方法和原理

在.net 1.1的时代,还没有TransactionScope类,因此很多关于事务的处理,都交给了SqlTransaction和SqlConnection,每个Transaction是基于每个Connection的.这种设计对于跨越多个程序集或者多个方法的事务行为来说,不是非常好,需要把事务和数据库连接作为参数传入. 在.net 2.0后,TransactionScope类的出现,大大的简化了事务的设计.示例代码如下: static void Main(string[] args) { usi

转:C#中TransactionScope的使用方法和原理

在.net 1.1的时代,还没有TransactionScope类,因此很多关于事务的处理,都交给了SqlTransaction和SqlConnection,每个Transaction是基于每个Connection的.这种设计对于跨越多个程序集或者多个方法的事务行为来说,不是非常好,需要把事务和数据库连接作为参数传入. 在.net 2.0后,TransactionScope类的出现,大大的简化了事务的设计.示例代码如下: static void Main(string[] args) { usi

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

在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. ? 1 2 var arr = []; console.log(Object.prototype.toString.call(arr)) //"[object Array]" 本文要讲的就是,toString方法是如何做到这一点的,原理是什么. ECMAScript 3 在ES3中,Object.prototype.toString方法的规范如下:

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

TransactionScope只要一个操作失败,它会自动回滚,Complete表示事务完成 实事上,一个错误的理解就是Complete()方法是提交事务的,这是错误的,事实上,它的作用的表示本事务完成,它一般放在try{}的结尾处,不用判断前台操作是否成功,如果不成功,它会自己回滚. 在.net 1.1的时代,还没有TransactionScope类,因此很多关于事务的处理,都交给了SqlTransaction和SqlConnection,每个Transaction是基于每个Connectio

Delphi 中DataSnap技术网摘

Delphi2010中DataSnap技术网摘 一.为DataSnap系统服务程序添加描述 这几天一直在研究Delphi 2010的DataSnap,感觉功能真是很强大,现在足有理由证明Delphi7该下岗了. DataSnap有三种服务模式,其中Service Application方式建立的Windows服务没有描述,描述部分是空的,可用如下方法添加服务描述: procedure TServerContainer.ServiceAfterInstall(Sender: TService);

Spring中@Component注解,@Controller注解详解(网摘)

在使用Spring的过程中,为了避免大量使用Bean注入的Xml配置文件,我们会采用Spring提供的自动扫描注入的方式, 只需要添加几行自动注入的的配置,便可以完成Service层,Controller层等等的注入配置. 使用过程中,在Service层中的实现类头上加@Compopnet注解,在Controller类头加@Controller注解,便完成了配置. 例如 在Controller中当我们调用某个Service时就不需要Set方法了,直接通过@Autowried 注解对Service

网摘 SQL Server

http://soft.chinabyte.com/database/215/12374715.shtml . 软件与服务 我们也在这里: . 企业计算 大数据 存储 软件与服务 数据库/开发 服务器 操作系统 网 络 安 全 . 您的位置: 比特网 > 软件与服务 > 正文 . 分享一个 SQLSERVER脚本 发布时间:2014-07-17 16:21:00来源:论坛 作者:译名 . . 关键字:数据库 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间.   这里共享一个脚

Jquery中$(document).ready() 和 JavaScript中的window.onload方法 比较

Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个(最后一个)