I am trying to learn how Entity Framework works. I understand that EF SaveChanges is basically a wrapper around a transactional update. I also understand that you can wrap two context’s in a TransactionScope if necessary.
I am using the Code First approach.
What I dont understand is how I would do an update like
UPDATE Inventory SET Available = Available - 1 WHERE Available > 0
In other words – How do I ensure that there is at least X Available inventory before doing the update?
I suppose I could write code that looks at the inventory of the product and verifies that there is enough inventory to complete a purchase:
if (Product.Inventory - quantityToPurchase < 0) throw new Exception(..)
But what about in scenario where two customers attempt to buy at the same time and the object fetched from the database for each customer claims to have 2 items in inventory? My logic above would not catch that.
How do I ensure that the SaveChanges() method only commits the changes to the object IF and ONLY IF (Available - quantity) is greater than 0?
Entity Framework by default uses Optimistic Concurrency. What I described in my original post is called Pessimistic Concurrency in EF. There are two attributes that can be used to achieve this.
First is
Timestampwhich will create arowversioncolumn in the table. EF will detect this automatically and will always add awhereclause to the update comparing the value of the property from the entity to the value of the column in the database. Theupdatestatement succeeds only if the two match. Therowversioncolumn is incremented by the server automatically. This ensures that you are always updating the same data that you have in memory (in the POCO). If someone else changes that row after you fetched it and before you updated it, the update will fail.Second is
ConcurrencyCheckwhich works simliar toTimestamp. It will cause the value of the POCO property to be included in thewhereclause. The big difference is that it will not update this column like therowversionwill.