我在带有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 –