我有一個商業案例,其中,對於給定源表中的每個記錄,需要對不同表中的多個更改進行處理,並且每個這些sourceTable記錄需要單獨處理。TPL與實體框架更新
所以我有以下pseodocode:
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的是,我需要更改到OtherTables1 & 2被保存在一個事務與調用每個正在處理的sourceRecord的tctx.ExecuteStoreCommand()。
另請注意,我需要將寫入到SourceTable的結果保存爲獨立於對TransactionScope中更新的表所做的更改。因此,我不能在同一個TransactionScope中包含sourceTable的更新,因爲如果該txn回退,我將不會記錄該異常。這樣,在整個過程結束時,我可以看到哪些sourceRecords失敗以及哪些成功。
上面的僞代碼完美地工作。
但是,我想利用這裏的並行性,並將foreach轉換爲Parallel.ForEach()。但後來我遇到了非常意外的錯誤(如調用ts.Complete()後的TransactionAbortedException,調用ctx.SaveChanges()時的NullReferenceException或設置sourceRecord的Result屬性之一時,有時會得到InvalidOperationException:EntityMemberChanged或EntityComplexMemberChanged被調用首先在具有相同屬性名稱的相同更改跟蹤器上調用EntityMemberChanging或EntityComplexMemberChanging)。
因此,我認爲並行,雖然完美的QUERIES,不適合EntityFramwork中的數據更新?我錯過了什麼,或者不瞭解並行性?我不明白爲什麼我的上述方法轉換爲使用並行性時會中斷。任何意見,將不勝感激。
我基本上通過創建一個WCF服務來解決這個問題,並且在try {}塊內調用它,而不是創建一個新的EF上下文根據我的上述代碼。然後,我不得不處理的問題是處理死鎖問題,但通過在服務方法中多次嘗試每次發佈很容易解決這個問題。 –