尽管更新冲突,但EF不会抛出DbUpdateConcurrencyException
我在Web客户端的Web API服务器上使用EF 6.x(代码优先),我需要实现并发处理。 问题是我甚至无法获得EF来生成exception。
我发现的大多数示例似乎都没有使用“分离实体”,其中DTO被发送到Web客户端,在那里它被更新,然后在以后保存回服务器(这是我的场景)。
假设我有公司记录:
public class Company { int CompanyId { get; set; } string CompanyName { get; set; } 1541627290 public byte[] RowVersion { get; set; } }
1)用户A上拉公司, Id
= 0, RowVersion
为0x0000000000002B0A
2)我运行UPDATE Company SET CompanyName = 'Acme Changed, Inc.' WHERE CompanyId = 0
UPDATE Company SET CompanyName = 'Acme Changed, Inc.' WHERE CompanyId = 0
以模拟其他用户的更改。 RowVersion
更改为0x0000000000002B0B
3)用户A将CompanyName更改为“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,而不是并发exception。
我错过了什么?
我需要一种方法来检测更改,删除等,以防止保存脏数据。 我想我可以滚动自己的检查,但实际的对象很复杂,有许多嵌套的子对象(一个或多个级别)。
关于此的最佳实践的任何指示也将受到赞赏……
我有这个工作。 在我的问题的第5步中,我改变了这一行:
dbCompany.RowVersion = updatedCompany.RowVersion;
对此:
Context.Entry(dbCompany).OriginalValues["RowVersion"] = updatedCompany.RowVersion;
现在EF在尝试保存脏数据时抛出DbUpdateConcurrencyException!
我正在使用Entity Framework的抽象,我无法访问EF上下文,但我发现了写作
updatedCompany.RowVersion.CopyTo(dbCompany.RowVersion, 0);
解决了这个问题。