2012-07-10 9 views
6

エンティティフレームワーク(4.3.1)で従来のデータアクセスコードを徐々に置き換える段階にあります。場合によっては、1つの作業単位で両方のデータアクセス方法を使用することを避けることはできません。理想的には、これは1つのトランザクションで実行する必要があります。ただし、古いコードでは、作業単位が完了し、EFが独自のトランザクションを管理するときにCommit()を呼び出すSqlTransactionが使用されます。TransactionScope内のSqlTransaction.Commitを無視する

私たちはTransactionScopeに「古い」コードと「新しい」コードをラップすることを考えました。ただし、TransactionScopeが完了していなくても、周囲のCommitはTransactionScopeが常に実行されます。このコードスニペットは、私の問題を示しています:scope.Complete()がヒットしていないとき

using (var conn = new SqlConnection("connection string")) 
{ 
    conn.Open(); 
    using (var scope = new TransactionScope()) 
    { 
    using (var tr = conn.BeginTransaction()) 
    { 
     using (var cmd = conn.CreateCommand()) 
     { 
     cmd.Transaction = tr; 
     cmd.CommandText = "some update statement"; 
     cmd.ExecuteNonQuery(); 
     } 
     tr.Commit(); 
    } 
    // In reality the code above is part of a legacy DAL, immutable. 
    // (can't insert SaveChanges before tr.Commit). 
    context.SaveChanges(); 
    if (<all ok>) // pseudo code for exception handling. 
     scope.Complete(); 
    } 
} 

更新ステートメントをまだコミットしています。

したがって、TransactionScopeを使用して、古いデータアクセスコードとコンテキスト内のSaveChangesを強制的に1つのトランザクションで実行することはできません。 または、SqlTransaction.Commitステートメントを無効にする方法はありますか?

TransactionScopeとSqlTransactionについてもっと多くの記事があることは知っていますが、すべて(正しく言うと)、TransactionScopeを使用する場合、SqlTransactionを使用する必要はありません。しかし、ここではSqlTransactionを使用しないオプションはありません。私たちは、独自のフレームワークであるSqlTransactionをコミットしていますが、トランザクションメカニズムにフックするAPIはありません。

+0

少なくとも接続にアクセスできますか? –

+0

@LadislavMrnkaいいえ、設定ファイルの接続文字列は別です。 –

答えて

7

scope.Complete()がヒットしなかった場合でも、更新ステートメントはコミットされます。

Oh no !! TransacationScopeは使用されていません。接続が(または内側)のTransactionScope開いている場合

のみ作品を自動参加。置く

Open内部接続は、その後、[通常]周囲TSコンテキストで自動的に参加されますよう(でも手動トランザクションと?)この問題を修正する必要がありTransactionScope

既存の接続をアンビエントトランザクションスコープに登録することができます:connection.EnlistTransaction(Transaction.Current)。あるいは、TSは、既存のトランザクション(例えば、トランザクション)から作成することができる。 new TransactionScope(transaction)がありますが、ここでは参考になるかもしれません。

完全に罰金場合は、手動トランザクションを作成するが、TS(落とし穴を考え出した後に!)より簡便な取引を扱ってます。..少なくともほとんどの場合:)コーディング

ハッピー!


TSは、 "UPDATE文" のために使用されていません。それはcontext.SaveChanges()のためにまだ[可能性として]使用されるでしょうから、新しい接続が自動的に登録されます。

私は平易な "入れ子になった"トランザクションについてはわかりませんが、上記のいくつかのオプションを提供しました。コンテキストで使用されている(封印された)APIを見ると、制限/制限に関するより多くの洞察を明らかにすることができます。

+0

あなたは正しいです! TSの後に 'Open'を置くと、TSは先導しています。そして、私は、接続が古いフレームワークの中で開かれているので、現実にはこれも起こるべきだと私は考えています。しかし、それは依然としてコミットしています。私はそこで起こっていることを少し深く掘り下げて、あなたの提案の1つがこれを解決できるかどうかを見なければならないでしょう。ありがとう、私はこれに戻ってきます。 –

+0

これは私を正しい軌道に導いた。私は、古いフレームワークでは、接続が必要以上に長く開いていることがわかりました。ですから、私が望むやり方でTransactionScopeを使用することは、古いコードを変更しなければ不可能です。私たちがしなければならないのは残念です。 –

関連する問題