Background
I've recently inherited this ASP.NET 4.8 project. I'm implementing functionality that sets one row in the database as a default record. This is backed by a SQL Server which has an UNIQUE index on the CustomerID column when the IsDefault bit column is set.
Problem
When a new default record is requested, I must set the existing default to False before updating the new record, otherwise the UNIQUE database constraint will be violated. Occasionally, the correct updates happen, but I cannot pinpoint the state in which this does happen. Sometimes it was when the application first started up, or when a database record was edited outside of the application.
Most subsequent requests never update the existing default record. Inspecting the SQL statement that is generated shows that the SQL UPDATE statement for the current default record is never actually generated by Entity Framework.
Here is the controller code, it is wrapped in the same using statement so each query uses the same dbContext:
CustomerPO existingPO = (from item in dbContext.CustomerPO
where (item.PurchaseOrderID == purchaseOrder.PurchaseOrderID)
select item).FirstOrDefault();
var currentDefault = (from item in dbContext.CustomerPO
where item.IsDefault && item.CustomerID == existingPO.CustomerID
select item).FirstOrDefault();
if (currentDefault != null && currentDefault.PurchaseOrderID != existingPO.PurchaseOrderID)
{
currentDefault.IsDefault = false;
}
dbContext.Entry(existingPO).CurrentValues.SetValues(purchaseOrder);
dbContext.SaveChanges();
return Ok(new { PurchaseOrderID = purchaseOrder.PurchaseOrderID });
What's Been Tried
- Specifying that the entire entity is modified. This results in the same issue.
dbContext.Entry(currentDefault).State = System.Data.Entity.EntityState.Modified;
- Specifying that the specific column has been modified. This results in the same issue.
dbContext.Entry(currentDefault).Property(e => e.IsDefault).IsModified = true;
- Iterating through the
dbContext.ChangeTracker.Entries()shows that thecurrentDefaultentity is marked asModifiedand theIsDefaultproperty is marked the same.
I've read through a few other posts online which describe the above. What I'm trying to accomplish seems to be possible, I'm just not getting what I expect to be the output.
Questions
To clarify, I can save the record just fine by making two SaveChanges calls to the dbContext. The fact that my above code works sporadically makes me think there is a caveat I am missing about Entity Framework.
- Is there some limitation that I'm encountering related to
UNIQUEindexes? - Are there other database context settings that need to be set to perform this kind of operation?
- Does EF not support multiple
UPDATEcalls in the way that this code is written? - Is a transaction necessary in this situation?
I appreciate any insight into this - documentation, links, personal experience, etc. Thanks.
existingPOandcurrentDefaultcan be the same object, in which case it will probably be default again afterCurrentValues.SetValues. You have to be 100% certain that this doesn't occur by validating it in code.