使用对象初始化构造的嵌套事务作用域会导致错误

时间:2013-03-07 01:49:42

标签: c# .net transactionscope object-initialization

在我的C#代码中,我使用的是嵌套的事务范围。我有一个实用程序类,它以相同的方式创建TransactionScope对象。外部范围和内部范围都以完全相同的方式构造。

如果我像下面的第一个例子一样构造TransactionScope对象,那么嵌套的事务范围可以很好地协同工作:

public static TransactionScope CreateTransactionScope()
{
   var transactionOptions = new TransactionOptions();
   transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
   transactionOptions.Timeout = TransactionManager.MaximumTimeout;
   return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
}

但是,如果我像这样构造TransactionScope对象,我会遇到异常:

public static TransactionScope CreateTransactionScope()
{
   var transactionOptions = new TransactionOptions
   {
      IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
      Timeout = TransactionManager.MaximumTimeout
   };
   return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
}

错误读取:“为TransactionScope指定的事务具有与为作用域请求的值不同的IsolationLevel。参数名称:transactionOptions.IsolationLevel ”。

有人可以向我解释为什么使用对象初始化会导致这种行为吗?

2 个答案:

答案 0 :(得分:2)

当外部事务隔离级别与您要分配给事务范围的外部事务隔离级别不同时,会发生此错误。 这意味着调用方法并尝试分配所需的隔离,事务管理器会检测到存在具有不同隔离级别的现有事务,并抛出异常。

var transactionOptions = new TransactionOptions
{
   IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
   Timeout = TransactionManager.MaximumTimeout
};

return new TransactionScope(TransactionScopeOption.RequiredNew,TransactionOptions);

RequireNew强制创建新的内部事务。 我建议进行动态检查,这是当前的隔离,类似于:

if (Transaction.Current != null && Transaction.Current.IsolationLevel != myIsolationLevel)
{
   scopeOption = TransactionScopeOption.RequiresNew;
}
编辑:正如评论中所建议的,值得一提的是,RequiresNew确实创建了一个新的事务,而且本质上它与外部事务是隔离的。我找到了一个非常好的阅读材料,它很好地解释了交易如何在这里工作:https://www.codeproject.com/articles/690136/all-about-transactionscope

答案 1 :(得分:1)

您是否绝对确定只交换上述方法会导致异常?它们应该在功能上100%相同。

只是干运行这两种变体都很好:

using (var aa1 = CreateTransactionScopeGood())
    using (var aa2 = CreateTransactionScopeGood())
        Console.WriteLine("this will be printed");

using (var aa1 = CreateTransactionScopeBad())
    using (var aa2 = CreateTransactionScopeBad())
        Console.WriteLine("this will be printed");

你能提供一种重现它的方法吗?

但是,只有在同一事务中混合使用不同的IsolationScope时,我才能重现您的异常,这确实会导致异常:

using (new TransactionScope(TransactionScopeOption.Required, new
        TransactionOptions { IsolationLevel = IsolationLevel.Chaos }))
    using (new TransactionScope(TransactionScopeOption.Required, new
            TransactionOptions { IsolationLevel = IsolationLevel.Serializable }))
        Console.WriteLine("this will not be printed");