EF not throwing DbUpdateConcurrencyException despite conflicting updates

匿名 (未验证) 提交于 2019-12-03 08:48:34

问题:

I am using EF 6.x (code-first) on a Web API server with web clients and I need to implement concurrency handling. The problem is that I cannot even get EF to generate an exception.

Most examples that I have found seems to not be using "detached entities", where the DTO is sent to a web client where it is updated and then saved back to the server at a later time (which is my scenario).

Let's say I have a Company record:

public class Company  {     int CompanyId { get; set; }     string CompanyName { get; set; }      [Timestamp]     public byte[] RowVersion { get; set; } } 

1) User A pulls up company with Id = 0, RowVersion is 0x0000000000002B0A

2) I run UPDATE Company SET CompanyName = 'Acme Changed, Inc.' WHERE CompanyId = 0 to simulate a change by another user. RowVersion changes to 0x0000000000002B0B

3) User A changes CompanyName to "Acme, The Great!" and clicks Save (from browser)

4) The Company DTO arrives at Web API server with CompanyName = "Acme, The Great!" and the old RowVersion = 0x0000000000002B0A

5) I retrieve the Company record from the DB, update it and save it:

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).     } } 

Instead of a concurrency exception, it just saves the record and updates RowVersion to 0x0000000000002B0C.

What am I missing?

I need a way to detect changes, deletion, etc. to prevent saving dirty data. I guess I could roll my own checks, but the actual objects are complex with many nested child objects (one or more levels).

Any pointers on best practices on this would also be appreciated...

回答1:

I got this working. In step 5 of my question, I changed this line:

dbCompany.RowVersion = updatedCompany.RowVersion;   

To this:

Context.Entry(dbCompany).OriginalValues["RowVersion"] = updatedCompany.RowVersion; 

Now EF throws a DbUpdateConcurrencyException when trying to save dirty data!



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!