2012-07-02 2 views
54

がある私はちょうど(System.TransactionsののTransactionScopeを作成するときに、私は任意の考えることはできませんので、デフォルトのIsolationLevelとしてシリアライズを使用することをお理由は、あるかもしれないもの疑問に思ってや代わりに、私は常にこのような定型コードを記述する必要がありなぜSystem.TransactionsのTransactionScopeの既定のIsolationLevel Serializableを

using(var transaction = TransactionScope()) { 
    ... // creates a Transaction with Serializable Level 
} 

)あなたは常にあなたのコードでそれを設定する必要がありますので、あなたがウェブ/ app.configを介して、デフォルトを変更することはできませんようだ:

var txOptions = new System.Transactions.TransactionOptions(); 
txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; 

using(var transaction = new TransactionScope(TransactionScopeOption.Required,txOptions)) { 
    ... // 
} 

アイデア?

+1

ボイラープレートコードをヘルパーメソッドに移動すると、この問題は再びあなたを悩ますことはありません。 – usr

答えて

68

実際にSerializableは、.NETがリリースされていない時期(1999年以前)、DTC(Distributed Transaction Coordinator)のプログラミング時からのデフォルトです。

DTCは、ネイティブISOLATIONLEVEL列挙を使用しています。現在のトランザクションによって読み取ら

ISOLATIONLEVEL_SERIALIZABLE データは、現在のトランザクション が終了するまで、別のトランザクションによって変更されない できます。現在の トランザクションに影響する新しいデータを挿入することはできません。 これは最も安全な分離レベルで、デフォルト値は ですが、最も低いレベルの並行性が可能です。

.NET TransactionScopeは、これらの技術の上に構築されています。

次に、DTCがデフォルト取引レベルとしてISOLATIONLEVEL_SERIALIZABLEを定義する理由は次のとおりです。私はDTCが1995年(確かに1999年以前)の年頃に設計されたからだと思います。その時点で、SQL標準はSQL-92(またはSQL2)でした。ここ

SQL-92は、トランザクション・レベルについてこう言われる、

SQLトランザクションは、分離UNCOMMITTED READされるレベル、COMMITTED READ、REPEATABLE READ、またはSERIALIZABLEを持っています。 SQLトランザクションの隔離レベル は、 のSQLデータまたはスキーマが、SQLデータまたは の影響によって影響を受け、SQLデータまたはスキーマの操作に影響を与える可能性がある度合いを定義します。 SQLトランザクション。 SQLトランザクション の分離レベルは、デフォルトでSERIALIZABLEです()。レベルは、 <set transaction statement>によって明示的に設定できます。

分離レベル SERIALIZABLEでの同時SQLトランザクションの実行は、直列化可能であることが保証されています。シリアライズ可能なexe- cutionは、 と同じエフェクトを生成する同じSQLトランザクションのシリアル実行と同じ結果をもたらすSQL-トランザクションを同時に実行する操作の実行と定義されています。シリアルEXE- は、次のSQLトランザクションが開始される前に各SQLトランザクションが完了して に実行されます。

+2

この非常に興味深い有益な答えをありがとう。 –

25

これは「デザイナーだけが間違いなく知っている」タイプの質問の1つだと思います。しかし、ここで私の2つのセントはどんなところでもあります:Serializableは、(ロックベースのRDBMSでのロックに関する、したがって同時のアクセス、デッドロックなどの)最も制限的な分離レベルですが、 "分離レベル(データの一貫性に関する)。

あなたのようなシナリオでは余分な作業が必要ですが(これが行われた;-)、デフォルトで最も安全なバリアントを選択するのが理にかなっています。

設定で変更できるようにすると、設定を手伝って完全に機能するアプリケーションを壊れたもの(他の何かと一緒に働くように設計されていない可能性があるため)。または、分離レベルを「ハードコーディング」することによって、引数を有効にすることで、アプリケーションが期待どおりに機能することを確認できます。おそらく、分離レベルは構成オプション(実際にはtransaction timeout)には適していません。

+2

"完全に機能するアプリケーションを壊れたアプリケーションにレンダリングすることができます" +1 – Steven

+2

シリアライズ可能な分離レベルであっても、通貨の問題が発生しないことを保証するものではありません。 – Steven

+1

@スティーブン:確かに。したがって、私の "_most_ safe"という言葉の使用;-) –

40

定型的なコードを書く削減する便利な方法がそうのようなビルダークラスでそれをラップすることです:

public static class TransactionScopeBuilder 
    { 
    /// <summary> 
    /// Creates a transactionscope with ReadCommitted Isolation, the same level as sql server 
    /// </summary> 
    /// <returns>A transaction scope</returns> 
    public static TransactionScope CreateReadCommitted() 
    { 
     var options = new TransactionOptions 
      { 
       IsolationLevel = IsolationLevel.ReadCommitted, 
       Timeout = TransactionManager.DefaultTimeout 
      }; 

     return new TransactionScope(TransactionScopeOption.Required, options); 
    } 
} 

トランザクションスコープを作成するとき、あなたはこのようにそれを使用することができます:

using (var scope = TransactionScopeBuilder.CreateReadCommitted()) 
    { 
     //do work here 
    } 

必要に応じて、他の一般的なトランザクションスコープのデフォルトをビルダークラスに追加できます。

+1

これは実際には、私のユースケースの "デフォルト" Transactionscopeを取得する中心的な場所を持っていたのと同じことです –

関連する問題