What is the purpose of the ConcurrencyStamp column in the AspNetUsers table in the new ASP.NET MVC 6 identity?
As the name state, it's used to prevent concurrency update conflict.
For example, there's a UserA
named Peter in the database
2 admins open the editor page of UserA
, want to update this user.
-
Admin_1
opened the page, and saw user called Peter. -
Admin_2
opened the page, and saw user called Peter (obviously). -
Admin_1
updated user name to Tom, and save data. NowUserA
in the db named Tom. -
Admin_2
updated user name to Thomas, and try to save it.
What would happen if there's no ConcurrencyStamp is Admin_1's update will be overwritten by Admin_2's update.
But since we have ConcurrencyStamp
, when Admin_1
/Admin_2
loads the page, the stamp is loaded. When updating data this stamp will be changed too.
So now step 5 would be system throw exception telling Admin_2 that this user has already been updated, since he ConcurrencyStamp
is different from the one he loaded.
From the source code itself
/// <summary>
/// A random value that should change whenever a role is persisted to the store
/// </summary>
public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString();
Basically, see it as it is named. A stamp that is used to identify the current version of the data. If you change it, so does the stamp.
So if two concurrent updates comes in at the same time, they must have the same stamp or one of them should be discarded.
Hence the name, ConcurrencyStamp
.
To follow up on Maxime's reply:
If you look at the implementation of IdentityDbContext in the OnModelCreating() method, you'll find:
builder.Entity<TUser>(b =>
{
....
b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
....
and in the UserStore.UpdateAsync(...)-method:
Context.Update(user);
try
{
await SaveChanges(cancellationToken);
}
catch (DbUpdateConcurrencyException)
{
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
So, it indeed does what it's supposed to do: prevent concurrent updates on a user object. The token is merely used "under the hood" in the ASP Identity EntityFramework module. Basically, if a concurrent update of one user object occurs, the DB context throws DbUpdateConcurrencyException.