我在帶有Web客戶端的Web API服務器上使用EF 6.x(代碼優先),我需要實現併發處理。問題是我甚至無法讓EF生成異常。EF不會拋出DbUpdateConcurrencyException,儘管發生衝突更新
我發現的大多數例子似乎都沒有使用「分離的實體」,DTO被髮送到Web客戶端進行更新,然後在稍後保存回服務器(這是我的場景) 。
比方說,我有一個公司的記錄:
public class Company
{
int CompanyId { get; set; }
string CompanyName { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
1)用戶A拉起公司Id
= 0,RowVersion
是0x0000000000002B0A
2)我跑UPDATE Company SET CompanyName = 'Acme Changed, Inc.' WHERE CompanyId = 0
來模擬另一個用戶的改變。 RowVersion
更改爲0x0000000000002B0B
3)用戶A將公司名稱更改爲「Acme,The Great!」並點擊保存(從瀏覽器)
4)公司DTO到達Web API服務器CompanyName
=「Acme,The Great!」和老RowVersion
= 0x0000000000002B0A
5)我從數據庫中檢索公司記錄,更新和保存:
public void UpdateCompany(Company updatedCompany)
{
var dbCompany = Context.Companies.SingleOrDefault(r => r.CompanyId == updatedCompany.CompanyId);
dbCompany.CompanyName = updatedCompany.CompanyName;
dbCompany.RowVersion = updatedCompany.RowVersion; // Set RowVersion to the passed in original RowVersion 0x0000000000002B0A
try
{
DbContext.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
// Expected: exception thrown (but does not happen).
}
}
相反併發異常的,它只是保存記錄和更新RowVersion
到0x0000000000002B0C 。
我錯過了什麼?
我需要一種方法來檢測更改,刪除等,以防止保存髒數據。我想我可以推出自己的檢查,但實際的對象與許多嵌套的子對象(一個或多個級別)複雜。
關於這個最佳做法的任何指針也將不勝感激...
您描述的問題沒有併發問題。您正在從數據庫獲取最新版本的數據並對其進行更新並保存。爲什麼EF會遇到問題。如果正在更新的行已被刪除或被其他查詢鎖定,或者兩個進程試圖同時更改同一行,則這些coluld會出現問題。但大部分時間,EF和SQL Server都盡力處理它。 –
@ChetanRanpariya我的想法是,EF會檢測到我試圖保存的記錄的RowVersion與DB中的記錄不匹配,從而知道該記錄很髒。如果不是這種情況,在這種情況下處理上述併發問題的正確/最佳做法是什麼? – Lars335
在您的示例中,您不保存之前檢索的行。您正在檢索並保存最新版本的行。我不確定你在這裏有什麼打算。您是在解決真正的應用程序問題還是隻是開始瞭解EF?這裏的用例究竟是什麼?如果實體被其他進程修改,您是否希望EF引發異常?你可以查看https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework -in-an-asp-net-mvc-application –