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

このエラーは、外部トランザクションの分離レベルが、トランザクション スコープに割り当てたいものと異なる場合に発生します。これは、メソッドを呼び出して必要な Isolation を割り当てようとすると、トランザクション マネージャーが別の分離レベルを持つ既存のトランザクションが存在することを検出し、例外をスローすることを意味します。

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");

再現する方法を教えてください。

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 に答える