RowVersion vs ConcurrencyToken In EntityFramework/EFCore

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.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

2 comments

  1. Thanks, nice article!
    By the way, does EF support pessimistic locks when the row is locked and concurrent transactions fail to start?

Leave a Reply

Your email address will not be published. Required fields are marked *