Entity Frameworkコンテキストと混在するADO.NETの全員に起こる問題に悩まされています。 私は、ADO.NETデータ・アダプターのような複数の方法を使用し、DBに対して直接CRUDコマンドを使用することによって、データベースにデータを処理して保存する大きな手順を持っています。すべてのプロシージャは、トランザクションをコミットまたはロールバックするためのDBConnection/DBTransactionおよびtry/catchブロックを作成および解放するブロックを使用して2つのラップされます。残念ながら、このルーチンの途中で、Entity Frameworkを使用して実装された保存プロシージャを思い出す必要があります。Entity Framework 5でExternal System.Common.DBTransactionを使用します。
公式のドキュメントによると、Entity Framework 5ではトランザクション関連のトランザクションとの接続を許可しています(デバッグモードで、SaveChanges()を呼び出すと機能するはずです。逆にデッドロックのためにTimeOutExceptionを受け取る、逆に新しい接続を渡すと)、残念ながらSaveChanges()の接続が終了し、関連付けられたトランザクションがコミットされた後!たとえ私がフラグ 'contextOwnsConnection'を設定したとしても!
私が知っている限り、EF5をEF6に移行すると作業がうまくいくはずですが、残念ながら私ができないのは、私が取り組んでいるプロジェクトが非常に大きく、それには多大な時間がかかります。
どのようにしてEF5で動作させることができますか?希望の結果を得るためのトリックやパターンはありますか? EF6の行動について正しいのですか? EF6移行の価値はありますか?
ここでは、自分のコードがどのように見えるかの簡単な例を示します。 プライバシー上の理由から、私は元のコードを投稿することはできませんが、ちょうどより多くの複雑さの多くで、このような状況を想像:私は非常にあなたの質問(複数可)を従わなかった
using(DbConnection conn = DBProvider.CreateConnection()){
//Open the created connection
conn.Open();
//Create a new transaction
using(DbTransaction tr = DBProvider.CreateTransaction()){
//Begin a new transaction
tr.Begin();
bool saveOk;
try{
//Updates customers by using dataadapter
dataAdapterCustomers.InsertCommand.Transaction = tr;
dataAdapterCustomers.UpdateCommand.Transaction = tr;
dataAdapterCustomers.DeleteCommand.Transaction = tr;
dataAdapterCustomers.Update();
//Updates stock items by using dataadapter
stockAdapterCustomers.InsertCommand.Transaction = tr;
stockAdapterCustomers.UpdateCommand.Transaction = tr;
stockAdapterCustomers.DeleteCommand.Transaction = tr;
stockAdapterCustomers.Update();
//...Many other DB accessing here...
//Updates stock quantity by using simple DBCommand
quantityUpdateCmd.Transaction = tr;
quantityUpdateCmd.ExecuteNonQuery();
//Updates stock statistics by using a simple DBCommand
updateStockStatsCmd.Transaction = tr;
updateStockStatsCmd.ExecuteNonQuery();
//...Many other DB accessing here...
//HERE:
//Creates a new activity and save it using EF.
//I use a UnitOfWork and i pass to it my connection and 'false' as contextOwnsConnection parameter
//(it 'll be used by the DBContext contained in my Unit of work)
using(ActivityUoW uow = new ActivityUoW(conn, false)){
Activity act = new Activity();
act.Name = "Saving activity";
act.Description = "Done by user";
act.Date = DateTime.Now;
uow.Activities.Add(act);
uow.SaveChanges();
}
//Based on activity result, launch a store procedure that makes other complex things.
UNFORTUNATELY THE CONNECTION HAS BEEN CLOSED AND TRANSACTION COMMITTED, SO THE FOLLOWING INSTRUCTION WILL FAIL.
launchActivityUpdateSpCmd.Transaction = tr;
launchActivityUpdateSpCmd.ExecuteNonQuery();
//...Many other DB accessing here...
//Data saved correctly
saveOk = true;
}
catch(Exception ex){
//There was an error during save
saveOk = false;
}
//Commit or rollback transaction according to save procedure result
if(saveOk)
tr.Commit();
else
tr.Rollback();
}
}
TransactionScopeのはいいですね、それは私のスコープ内のトランザクションを設定するために働く必要があります。しかし、EF SaveContext()の後に接続を閉じるとどうなりますか? EFはトランザクションスコープでDbConnectionを開いたままにしますか?私がそうでなければ、EF5からEF6への移行を離れて何をすることができますか? – GiveEmTheBoot
接続オブジェクトが使用ブロックにあります。接続は切断されます。ブロック呼び出しを使用Dispose()。 –
はい、私はそれを知っていますが、launchActivityUpdateSpCmdコマンドはどうでしょうか?以前のコード行のEF5 SaveChanges()動作のために、その時点で接続がすでに閉じられているため、機能しません。 – GiveEmTheBoot