We have seen some basic concepts related to database concurrency, concurrency control and concurrency conflicts in previous article. Now, in this article, let’s have a look at how optimistic concurrency can be implemented with .NET core.
How to implement ?
An optimistic concurrency assumes that there would not be concurrent updates, so it allows multiple processes or users to read and update the data. But in case concurrent updates happen, then it uses concurrency tokens to identify if the version from the update is matching with version from the database.
A concurrency token is a property is used to identify the version. There are two ways to implement optimistic concurrency with EF Core. Both of them are explained below.
A property from EF core entity can be marked as concurrency token by using ConcurrencyCheck attribute or IsConcurrencyToken method from Fluent API. Below code shows how to use data annotation and fluent API to configure concurrency token.
Concurrency Token vs Timestamp
One question that is not answered yet – what is the difference between the two approaches mentioned above ?
A ConcurrencyCheckAttribute (or IsConcurrencyToken fluent API) marks a property and EF core uses that property to identify different versions. But EF core does not really generates the value of this property. An application is supposed to generate the values of that property.
Now, a Timestamp attribute (or IsRowVersion fluent API) marks a property and EF core uses it for identifying different version. But in this case, EF core automatically generates values for this property. Application does not need to write any logic to generate values for that property.
What happens after implementing it ?
Whenever an update or delete operation is performed on an entity which has a concurrency token configured, EF core compares the value of token from the request with the value of token from database table.
- If both values match, then the operation is performed.
- If the values don’t match, then update or delete operation is aborted and EF core throws an
If EF core throws
DbUpdateConcurrencyException, application has choice to
- Either abort operation and ask user to restart operation from UI
- OR application can handle this exception to prepare new set of changes (including updating row version) and retry the operation with updated values. Then some kind of retry policy can be implemented to retry with updated values.
- OR application can log conflicted changes to a conflict database store so that the conflicts can be manually resolved by some user.
I hope you find this information useful. Let me know your thoughts.