I recently got asked a pretty good question about EFCore (Although it does also apply in general to database concepts), and that was :
Should I use RowVersion or ConcurrencyToken for optimistic concurrency?
And the answer is “It depends” and even more specifically, “Do you know what the difference, or lack thereof, there is between the two?”
Let’s rewind a little bit and start with what exactly are Concurrency Tokens, then what is a RowVersion, then finally, how do they compare.
What Is A Concurrency Token?
A concurrency token is a value that will be “checked” every time an update occurs on a database record. By checked what I specifically mean is that the existing value will be used as part of a SQL WHERE statement, so that should it have changed from underneath you, the update will fail. This might occur if two users are trying to edit the same record at the same time.
Or in very crude lucidchart form :
When UserB is updating the same record as UserA, at worst he is overwriting details from UserA unwittingly, but even at best he is writing details to a record using knowledge from his read that may be outdated by the update from UserA.
A concurrency token fights this by simply checking that information contained in the original read, is the still there on the write. Let’s imagine that we have a database table called “User” that looks like so :
Id int FirstName nvarchar(max) LastName nvarchar(max) Version int
Normally a SQL update statement without a concurrency token might look like so :
UPDATE User SET FirstName = 'Wade' WHERE Id = 1
But if we use the Version column as a concurrency token, it might instead look like :
UPDATE User SET FirstName = 'Wade', Version = Version + 1 WHERE Id = 1 AND Version = 1
The Version value in our WHERE statement is the value we fetched when we read the data originally. This way, if someone has updated a record in the time it took us to read the data and then update it, the Version is not going to match and our Update statement will fail.
In Entity Framework/EF Core, we have two ways to say that a property is a ConcurrencyToken. If you prefer using DataAnnotations you can simply apply an attribute to your models.
[ConcurrencyCheck] public int Version { get; set; }
Or if you prefer Fluent Configurations (Which you should!), then it’s just as easy
modelBuilder.Entity<People>() .Property(p => p.Version) .IsConcurrencyToken();
But There’s A Catch!
So that all sounds great! But there’s a catch, a small one, but one that can be quite annoying.
The problem is that short of some sort of database trigger (ugh!), or some sort of database auto increment field, it’s up to you, the developer, to ensure that you increment the version everytime you do an update. Now you can obviously write some EntityFramework extensions to get around this and auto increment things in C#, but it can complicated really fast.
And that’s where a RowVersion comes in.
What Is A RowVersion?
Let’s start in pure SQL Server terms what a RowVersion is. RowVersion (Also known as Timestamp, they are the same thing), is a SQL column type that uses auto generated binary numbers that are unique across that database, and stamped on records. Any time a record is inserted or updated on a table with a row version, a new unique number is generated (in binary format) and given to that record. Again, the RowVersions are unique across that entire database, not just the table.
Now in EntityFramework/EFCore it actually takes a somewhat different meaning because of what the SQL RowVersion is actually used to *achieve*.
Typically inside EF, when someone describes using a RowVersion, they are describing using a RowVersion/Timestamp column as a *ConcurrencyToken*. Now if you remember earlier the issue with just using a pure ConcurrencyToken was that we had to update/increment the value ourselves, but obviously if SQL Server is auto updating using RowVersion, then problem solved!
It actually gets more interesting if we take a look at how EFCore actually works out whether to use a RowVersion or not. The actual code is here : https://github.com/dotnet/efcore/blob/master/src/EFCore/Metadata/Builders/PropertyBuilder.cs#L152
public virtual PropertyBuilder IsRowVersion() { Builder.ValueGenerated(ValueGenerated.OnAddOrUpdate, ConfigurationSource.Explicit); Builder.IsConcurrencyToken(true, ConfigurationSource.Explicit); return this; }
Calling IsRowVersion() is actually shorthand for simply telling EFCore that the property is a ConcurrencyToken and it’s AutoGenerated. So in actual fact, if you added both of these configurations to a property manually, EF Core would actually treat it like a RowVersion even though you haven’t explicitly said it is.
We can see this by checking the code that asks if a column is a RowVersion here : https://github.com/dotnet/efcore/blob/master/src/EFCore.Relational/Metadata/IColumn.cs#L56
bool IsRowVersion => PropertyMappings.First().Property.IsConcurrencyToken && PropertyMappings.First().Property.ValueGenerated == ValueGenerated.OnAddOrUpdate;
So all it actually does is interrogate whether the column is a concurrency token and auto generated. Easy!
I would note that if you actually had a column that you auto incremented some other way (DB Trigger for example), and was also a concurrency token.. I’m pretty sure EFCore would have issues actually handling this, but that’s for another day.
In EntityFramework you can setup a RowVersion on a property like so for DataAnnotations :
[TimeStamp] public byte[] RowVersion{ get; set; }
And for Fluent Configurations:
modelBuilder.Entity<People>() .Property(p => p.RowVersion) .IsRowVersion();
Even though you specify that a column should be a RowVersion, the actual implementation of how that works (e.g. The datatype, specific settings on how that gets updated), is actually very dependent on the SQL Server (And SQL C# Adapter). Different databases can implement RowVersion how they like, but typically in SQL Server atleast, it’s a byte[] type.
Note that when using RowVersion with EntityFramework, there is nothing more you really need to do to get up and running. Anytime you update a record with a RowVersion property, it will automatically add that column to the WHERE statement giving you optimistic concurrency right out of the box.
So ConcurrencyToken vs RowVersion?
So if we go back to the original question of when you should use Concurrency Token vs when you should use a RowVersion. The answer is actually very simple. If you want to use a ConcurrencyToken as an auto incremented field, and you don’t actually care how it gets incremented or the data type, then use RowVersion. If you care about what the data type of your concurrency token should be, or you specifically want to control how and when it gets updated, then use Concurrency Token and manage the incrementing yourself.
What I’ve generally found is that when people have suggested to me to use Concurrency Token’s, typically what they actually mean is using RowVersion. Infact it’s probably easier to say that RowVersion (In the Entity Framework sense) is a *type* of Concurrency Token.
Thanks, nice article!
By the way, does EF support pessimistic locks when the row is locked and concurrent transactions fail to start?
If you just mean DB Transactions with locking, then yes it does!
Correct me if I’m wrong, but RowVersion doesn’t help if you’re saving the “aggregate root”. You might have updated a field of a separate table that represents a child property of the aggregate. You need to have a version counter on the aggregate and increment that instead
If we are still talking SQL Server, and you are updating two tables in a parent/child relationship, both can have a RowVersion and both will be checked accordingly. When you update two tables at once in EF Core (By just calling Save), it’s wrapped in a transaction so if either are incorrect it will back out of both updates.
Now in terms of the concurrency token, yes, you would have to increment both (And manage both) yourself. Hence why for most purposes, RowVersion is what you want.
Nice article, thanks!
Could you clarify please that I understand things correctly.
For instance I have entity with single column so if I change something it would be this column only. And if I want to protect this table from parallel updating I can do it via ConcurrencyToken on this property without any additional moves for incrementing this value because updating already does it.
It also will work with several columns with ConcurrencyToken which I always update. This is just hypothetical example because it is quite messy solution.
Am I right in my conclusion?
That would be correct. So if you are always updating the column marked as concurrency token (Either because it’s the only column on the table or just because it’s always updated when you update other columns), then yes, it will be protected from parallel updating.
Hi,
You mentioned:
“I would note that if you actually had a column that you auto incremented some other way (DB Trigger for example), and was also a concurrency token.. I’m pretty sure EFCore would have issues actually handling this, but that’s for another day.”
Do you have an example/blog/post for it?
Thanks
No I don’t unfortunately. Looking back, it’s because the only way EF Core determines if a RowVersion is a RowVersion is if it’s a concurrency token AND auto generated. But that doesn’t really work in some cases because :
– A RowVersion is always a concurrency token and auto generated
– A column that is auto generated and a concurrency token is *not* always a RowVersion
But I don’t have anything more unfortunately as I haven’t ran into the problem myself.