2013-02-19 35 views
6

私はデータベースにデータを保存するときに、IsolationLevelをSerializableに設定してTransactionScopeを使用しました。トランザクション完了後のTransactionScope IsolationLevelの変更

TransactionOptions options = new TransactionOptions 
     { 
      IsolationLevel=IsolationLevel.Serializable 
     }; 


using (var transaction = new TransactionScope(TransactionScopeOption.Required,options)) 
{ 
    transation.Complete(); 
} 

実行が終了した後、私はTransactionScopeIsolationLevelを変更したいと思います。

編集私が理解することである

これ、IsolationLevelをその後、トランザクションを完了した後、接続オブジェクトが閉じられ、接続プールに戻り、他のいくつかの要求が到着したとき、それはからその接続オブジェクトをフェッチシリアライズに設定している場合以前のIsolationLevelによって影響を受けます。だから私はすべてのトランザクションの後に分離レベルをデフォルトに変更したい。

答えて

5

あなたはそうです:接続をプールに戻すときに分離レベルはリセットされません。これは恐ろしい動作ですが、我々はそれで立ち往生している...

2つの戦略があります。これはあなたのアプローチです:

  1. が戻る前に、分離レベルをリセットします。
  2. 明示的なトランザクション(またはTransactionScope)との接続を使用して、分離レベルが保証されるようにしてください。

後者をお勧めします。

あなたが(1)をすることを強くお勧めする場合は、TransactionScopeを閉じた後に隔離レベルを変更するだけで、接続オブジェクトでこれを行う必要があります。例:

using (SqlConnection connection = new SqlConnection(connectionString)) 
{ 
    using (var transaction = new TransactionScope(TransactionScopeOption.Required,options)) 
    { 
     connection.Open(); //open inside of scope so that the conn enlists itself 
     transation.Complete(); 
    } 
    //conn is still open but without transaction 
    conn.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL XXX"); //pseudo-code 
} //return to pool 

これは機能しますか?

+0

私は他のより良いオプションを受け入れる準備ができていますが、明示的なトランザクションですべての接続を開くように提案しているので、システムでオーバーヘッドが大きくなるとは思わないでしょう。私は膨大な数のエンドポイントを持つ巨大なアプリケーションを持っていますが、TransactionScopeを使用しているシナリオは2つしかありません。あなたはそのようなことについて何をお勧めしますか? – MegaMind

+0

トランザクションのオーバーヘッドは、すべてのステートメントが暗黙のトランザクションを使用するため、ほとんど何もありません。すべてを移行できない場合は、実際にはアプローチが良いアイデアかもしれません。ハックですが、実用的な解決策です。私はそれに大きな問題は見当たらない。 – usr

+0

はconn.ExecuteCommand( "SET TRANSACTION ISOLATION LEVEL XXX")を実行します。作業?誰もそれを試しましたか? – hazimdikenli

2

私はこれで少し苦しんできました。幸いにも、接続文字列ロジックは集中化されました。私がしたのは、Transaction.Currentがnullでない(接続がトランザクションスコープ内にあることを意味する)場合、接続文字列のアプリケーション設定を変更することでした。

このようにして、TransactionScope接続は他の接続とプールされません。

関連する問題