使用TransactionScopeOption 管理事务流

Posted 海~~D

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用TransactionScopeOption 管理事务流相关的知识,希望对你有一定的参考价值。

可通过调用一个方法来嵌套事务范围,该方法在使用其自己范围的方法中使用 TransactionScope,下面示例中的 RootMethod 方法就是前者这样的方法。

 1     void RootMethod()
 2     {
 3          using(TransactionScope scope = new TransactionScope())
 4          {
 5             
 6               SomeMethod();
 7               scope.Complete();
 8          }
 9     }
10      
11     void SomeMethod()
12     {
13          using(TransactionScope scope = new TransactionScope())
14          {
15             
16               scope.Complete();
17          }
18     }

 

最顶层事务范围称为根范围。

TransactionScope 类提供了多个重载构造函数,它们接受 TransactionScopeOption 类型的枚举,而该枚举定义范围的事务行为。

TransactionScope 对象有以下三个选项:

  • 联接环境事务,或者在环境事务不存在的情况下创建新的环境事务。

  • 成为新的根范围,也就是说,启动一个新事务并使该事务成为其自己范围中的新环境事务。

  • 根本不参与事务。因此没有环境事务。

如果用 Required 实例化范围并且存在环境事务,则该范围会联接该事务。相反,如果不存在环境事务,该范围就会创建新的事务并成为根范围。这是默认值。在使用Required 时,无论范围是根范围还是仅联接环境事务,该范围中的代码都不需要有不同的行为。该代码在这两种情况下的行为应相同。

如果用 RequiresNew 实例化范围,则它始终为根范围。它会启动一个新事务,并且其事务成为该范围中的新环境事务。

如果用 Suppress 实例化范围,则无论是否存在环境事务,范围都从不参与事务。用此值实例化的范围始终使其环境事务为 null

下表概括了上述这些选项。

 
TransactionScopeOption是否存在环境事务范围参与

Required

参与新事务(将成为根范围)

Requires New

参与新事务(将成为根范围)

Suppress

不参与任何事务

Required

参与环境事务

Requires New

参与新事务(将成为根范围)

Suppress

不参与任何事务

在 TransactionScope 对象联接现有环境事务时,除非范围中止该事务,否则释放范围对象的操作可能并不会结束事务。如果环境事务是由根范围创建的,则仅当释放根范围时,才会对事务调用 Commit。如果事务是手动创建的,则它将在中止或由其创建者提交时结束。

下面的示例演示一个 TransactionScope 对象,该对象创建了三个嵌套的范围对象,并用不同的 TransactionScopeOption 值对其中每个对象进行了实例化。

 1     using(TransactionScope scope1 = new TransactionScope()) 
 2     //Default is Required 
 3     { 
 4          using(TransactionScope scope2 = new 
 5           TransactionScope(TransactionScopeOption.Required)) 
 6          {
 7          ...
 8          } 
 9      
10          using(TransactionScope scope3 = new TransactionScope(TransactionScopeOption.RequiresNew)) 
11          {
12          ...
13          } 
14      
15          using(TransactionScope scope4 = new 
16             TransactionScope(TransactionScopeOption.Suppress)) 
17         {
18          ...
19         } 
20     }

 

下面的示例演示一个不包含任何环境事务的代码块,它使用 Required 创建了一个新范围 (scope1)。范围 scope1 是根范围,因为它创建了一个新事务(事务 A),并使事务 A 成为环境事务。Scope1 后来又创建了三个对象,并用不同的 TransactionScopeOption 值对其中每个对象进行了实例化。例如,scope2 是用 Required 创建的;由于存在环境事务,因此该范围联接 scope1 所创建的第一个事务。请注意,scope3 是新事务的根范围,而 scope4 则没有环境事务。

虽然 TransactionScopeOption 的默认值和最常用的值是 Required,但其他各值都有其独有的用途。

如果要保留代码段所执行的操作,并且不希望在操作失败的情况下中止环境事务,此时 Suppress 十分有用。例如,在要执行日志记录或审核操作时,或者在无论环境事务提交还是中止都要将事件发布给订户时。使用此值,可以在事务范围中包含非事务代码段,如下面的示例所示。

    using(TransactionScope scope1 = new TransactionScope())
    {
         try
         {
              //Start of non-transactional section 
              using(TransactionScope scope2 = new
                 TransactionScope(TransactionScopeOption.Suppress))
              {
                   //Do non-transactional work here
              }
              //Restores ambient transaction here
       }
         catch
         {}
       //Rest of scope1
    }

 

以上是关于使用TransactionScopeOption 管理事务流的主要内容,如果未能解决你的问题,请参考以下文章

将 TransactionScope 与实体框架 6 一起使用

本地事务

transactionscope报“此操作对该事务的状态无效”问题

事务处理器内的C#,SQL SP通过超时结束事务

如果外部事务范围未完成,内部事务范围会回滚吗?

[C#] 排除无须纳入交易的查询,避免产生不必要的分散式交易 (Distributed Transaction)