特定のソーステーブル内の各レコードについて、異なるテーブルの変更を行う必要があり、これらの各sourceTableレコードを個別に処理する必要があるビジネスケースがあります。Entity Frameworkアップデートを使用したTPL
MyEntityFrameworkContext ctx;
foreach (sourceRecord sr in ctx.sourceTable)
{
try
{
using (MyEntityFrameworkContext tctx = new MyEntityFramworkContext)
{
string result1 = MakeUpdatesToSomeOtherTable1(tctx);
sr.Result1 = result1;
string result2 = MakeUpdatesToSomeOtherTable2(tctx);
sr.Result2 = result2;
// will be more tables here.
using (TransactionScope ts = new TransactionScope)
{
tctx.SaveChanges; // to save changes made to OtherTable1 and OtherTable2
tctx.ExecuteStoreCommand("SQL that makes a few other changes related to sourceRecord to tables that are NOT in the EF context");
ts.Complete();
}
}
}
catch (Exception ex)
{
sr.ExceptionResult = ex.Message();
}
});
ctx.SaveChanges(); // to save all changes made to sourceTable.
ループ内のTCtxとのTransactionScopeの理由は、私はへの呼び出しで1つのトランザクションで保存するOtherTables1 & 2への変更を必要とするということである。
は、だから私は、次のpseodocodeを持っています処理される各sourceRecordのためのtctx.ExecuteStoreCommand()。
また、私は、SourceTableに書き込まれた結果を、TransactionScopeで更新されたテーブルの変更とは別に保存する必要があることにも注意してください。したがって、同じTransactionScopeにsourceTableの更新を含めることはできません。なぜなら、txnがロールバックされると、例外の記録がないからです。このようにして、プロセス全体の最後に、どのソースレコードが失敗したのか、どのレコードが成功したのかを知ることができます。
上記の擬似コードは完全に機能します。
ただし、ここでは並列処理を利用して、foreachをParallel.ForEach()に変換しました。しかし、ts.Complete()、NullReferenceExceptionを呼び出した後、TransactionAbortedExceptionのような予期しないエラーが発生しました.ctx.SaveChanges()を呼び出すとき、またはsourceRecordのResultプロパティの1つを設定すると、時々InvalidOperationExceptionが発生します:EntityMemberChangedまたはEntityComplexMemberChangedは同じプロパティ名を持つ同じ変更トラッカーで最初にEntityMemberChangingまたはEntityComplexMemberChangingを呼び出します)。
したがって、並列性はQUERIESには適していますが、EntityFramworkのデータ更新には適していないと思いますか?私は何が欠けているのか、あるいは並列性について理解していないのですか?なぜ私の上記のアプローチが並列化を使用するように変換されたときに壊れているのか分かりません。アドバイスをいただければ幸いです。
WCFサービスを作成して、これをtry {}ブロック内で呼び出すことで解決しました。上記のコードに従って新しいEFコンテキスト。それで私が対処しなければならなかった問題はデッドロックと関係していましたが、それはサービス方法の中で何度も各投稿を試すことで簡単に解決されました。 –