5

在我的 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 ”。

谁能向我解释为什么使用对象初始化会导致这种行为?

4

2 回答 2

3

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

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

于 2016-08-19T10:48:27.660 回答
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");

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

但是,只有在同一事务中混合不同的 s 时,我才能重现您的异常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");
于 2013-10-11T07:24:12.837 回答