使用EF DbContext。我的實體對象有rowversion列(SQL Compact版本第4版),它用於併發檢查(ConcurrencyMode = Fixed,StoreGeneratedPattern = Computed)。DbContext,處理併發異常
要強制實現併發異常,從UI讀取2種不同形式的相同表記錄,編輯它們中的每一個,然後一個接一個地保存。以下代碼執行實際的保存操作。
當點擊第二個窗體上的保存按鈕時,按預期發生併發錯誤。但是, 在從數據庫中複製原始值之後,第二次嘗試時異常仍然存在。只有第三次嘗試成功沒有任何錯誤。有人能解釋我可能會導致這個問題嗎?
try
{
_ctx.SaveChanges(); //first attempt
}
catch (Exception ex)
{
if (ex is DbUpdateConcurrencyException)
{
var exc = ex as DbUpdateConcurrencyException;
foreach (var entry in exc.Entries)
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
try
{
_ctx.SaveChanges(); //second attempt
}
catch (Exception ex2)
{
if (ex2 is DbUpdateConcurrencyException)
{
var exc2 = ex2 as DbUpdateConcurrencyException;
foreach (var entry in exc2.Entries)
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
try
{
_ctx.SaveChanges(); //third attempt
}
catch (Exception ex3)
{
System.Windows.MessageBox.Show(ex3.Message);
}
}
}
}
}
編輯:我發現它發生在我通過UI進行更新時。如果在上面的代碼,第一次嘗試之前,我做了什麼如下:
var _ctx2 = new MyDbContext();
var myEntity = _ctx2.MyEntities.Where(ent => ent.Id == 2).Single();
myEntity.Name = "My new name";
_ctx2.SaveChanges();
_ctx2.Dispose();
然後代碼工作正常,因爲myEntity所的另一個實例是通過UI更新;即第二次嘗試將拯救我的實體。 而且,問題出在下面一行:
foreach (var entry in exc.Entries)
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
因爲,當通過UI更新,exc.Entries返回沒有哪個併發錯誤發生的實體,但它的導航屬性的實體。
在這種情況下,MyEntity是一個樹狀自引用實體,它具有兩個導航屬性:ParentEntity和Children。
因此,在第一次保存嘗試後,我在exc.Entries中的內容是ParentEntity(處於未更改狀態),並且只有在第二次保存嘗試後,exc.Entries纔會返回引發併發錯誤的實際實體。
'注意:'您可以使用'catch(DbUpdateConcurrencyException ex)'而不是使用if檢查異常類型。 – NaveenBhat