2012-02-23 17 views
4

私は共有したい問題があります。文脈はちょっと乱雑ですから、私は説明の中で最善を尽くそうとします。SaveChangesとExecuteStoreCommandを使用したトランザクション操作

多くのエンティティでトランザクション操作を作成する必要があります。私はEF CodeFirstで作業していますが、変更できないレガシーデータベースを使用しています。データベースよりも一貫性のあるモデルを作成するために、自分で作成したより洗練されたエンティティにデータベース情報を投影しています。

私はさまざまなコンテキストを使用する必要があるため、私の初期の考えは過去に私に良い結果をもたらしたTransactionScopeを使用することでした。なぜ私は異なった文脈が必要なのですか? dbのさまざまな問題のため、私は1回の操作(UnitOfWork)でのみ更新を行うことはできません。 SaveChanges()の後にのみ表示される異なるIDを取得する必要があります。

using (var scope = new TransactionScope()) 
{ 
    Operation1(); 
    Operation2(); 
    Operation3(uses ExecuteStoreCommand) 
    SaveChanges(); 

    Operation4(); 
    SaveChanges(); 
} 

私はのTransactionScopeを使用するためには、(オブジェクトにコンテキストを渡し、そして、私はそれをやっている)私はすべての操作の間で同じ接続を共有する必要がある、ということを知っています。ただし、ExecuteStoreCommandを使用する操作のいずれかを実行するか、最初のSaveChangesの後に何らかの更新を試みると、MSDTCエラー(分散トランザクションのサポートが無効)またはさらに珍しい、がアンロードされます。ドメイン

少なくともこのシナリオでは最良の方向性を知っていれば誰かが私を助けてくれるのか分かりません。

おかげでたくさん、

+1

エンティティ接続がボンネットの下に新しい接続を開くように見えます。おそらく、あなたは[StateChange](http://msdn.microsoft.com/en-us/library/system.data.common.dbconnection.statechange.aspx)をフックして詳細を知ることができます。 –

+0

異なるデータベースに接続している(またはSql Server 2005を使用している)場合、トランザクションは分散トランザクションに昇格しています。 Sql Server 2005を使用している場合、EFが接続を複数回開くため、トランザクションは自動的に分散トランザクションに昇格されます。複数のコンテキスト間で同じ接続を共有したい場合は、トランザクション内で接続を開く必要があります(トランザクション内で自動的に接続を開始する必要があります)。接続をコンテキスト・コントローラに渡します。 EFは開かなかった接続を閉じません。 – Pawel

+0

EFが接続を閉じて再度開くことはないので、独自の接続を開くこともSql Server 2005の分散トランザクションへのトランザクションの昇格を禁止する方法であることに注意してください。 – Pawel

答えて

6

この回答を見てください:
Entity Framework - Using Transactions or SaveChanges(false) and AcceptAllChanges()?
答えは、複数のデータコンテキスト上で、トランザクションを持つ必要がまさにありません。

この投稿はTransactions and Connections in Entity Framework 4.0に投稿されました。

シンプルなソリューションが必要な人には、トランザクションにExecuteStoreCommandとSaveChangesを混在させる必要がある場合に、ここで私が使用しているものを紹介します。

using (var dataContext = new ContextEntities()) 
{ 
    dataContext.Connection.Open(); 
    var trx = dataContext.Connection.BeginTransaction(); 

    var sql = "DELETE TestTable WHERE SomeCondition"; 
    dataContext.ExecuteStoreCommand(sql); 

    var list = CreateMyListOfObjects(); // this could throw an exception 
    foreach (var obj in list) 
     dataContext.TestTable.AddObject(obj); 
    dataContext.SaveChanges(); // this could throw an exception 

    trx.Commit(); 
} 
+0

それは素晴らしい情報でした、ありがとうございましたRalph – IoChaos

+1

コンテキストがスコープから外れたとき、つまりusingステートメントの最後に接続が自動的に閉じられました。 –

+0

ありがとうございました! –

関連する問題