Reputation: 11407
I'm using Entity Framework on MS-SQL database. I'm implementing a PUT web endpoint to update a "response set".
If the caller indicates forceSave = true, I want to clobber the record even though the RowVersion does not match.
This is my code, but it does not work....
[HttpPut, Route("ResponseSets/{id:int}")]
public IHttpActionResult UpdateResponseSet(int id,
[FromBody] ResponseSet responseSetForUpdate,
[FromUri]bool? forceSave = false)
{
var db = new MyContext();
var responseSet = db.ResponseSets.FirstOrDefault(x => x.ResponseSetId == id);
if (!responseSet.RowVersion.SequenceEqual(responseSetForUpdate.RowVersion) && !forceSave.Value)
{
return new NegotiatedContentResult<LockingUser>(HttpStatusCode.Conflict,
new LockingUser(responseSet.LastUpdatedByUser), this);
}
responseSet.ResponseData = responseSetForUpdate.ResponseData;
responseSet.LastUpdatedByUser = HttpContext.Current.User.Identity.Name ?? "Anonymous";
responseSet.LastUpdatedDateTime = DateTime.Now;
db.SaveChanges();
return Ok();
}
Mostly it works! However, sometimes I get DBConcurrencyException
from the SaveChanges()
. I think it is because there is a race condition. After I read the database with FirstOrDefault
but before I write the database with SaveChanges
another process might update the row and change the RowVersion! Is there any way to disable RowVersion checking?
I thought about using a Transaction begin/end, but obviously that won't help.
I thought about writing a loop, so that if I get DBConcurrencyException, then it will read the RowVersion again, and try to write again... until success... but jeez that feels hacky.
Upvotes: 0
Views: 305