What is the purpose of the ConcurrencyStamp column in the AspNetUsers table in the new ASP.NET MVC 6 identity?

asp.net MvcConcurrencyDatabase SchemaIdentityasp.net Core-Mvc

asp.net Mvc Problem Overview


What is the purpose of the ConcurrencyStamp column in the AspNetUsers table in the new ASP.NET MVC 6 identity?

This is the database schema of the AspNetUsers table:

enter image description here

It is also there in the AspNetRoles table:

enter image description here

As I remember it wasn't there in the ASP.NET MVC 5 identity.

What I've noticed so far is that it seems to have GUID values as it is defined with the following code:

/// <summary>
/// A random value that must change whenever a user is persisted to the store
/// </summary>
public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString();

But this documentation is not sufficient for me to understand in which situations it is used.

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

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.

  1. Admin_1 opened the page, and saw user called Peter.
  2. Admin_2 opened the page, and saw user called Peter (obviously).
  3. Admin_1 updated user name to Tom, and save data. Now UserA in the db named Tom.
  4. 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.

Solution 2 - asp.net Mvc

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.

Solution 3 - asp.net Mvc

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.

Solution 4 - asp.net Mvc

Also important to realize that this is actually a data layer feature. The schema for Identity defines the column as being a concurrency column but doesn't actually use it.

There's no logic going on inside the Identity codebase - it's only when EFCore actually goes to save it that it kicks in.

https://docs.microsoft.com/en-us/ef/core/modeling/concurrency

https://stackoverflow.com/questions/5980128/ef-code-first-isconcurrencytoken?rq=1

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNikolay KostovView Question on Stackoverflow
Solution 1 - asp.net MvcSteven.XiView Answer on Stackoverflow
Solution 2 - asp.net MvcMaxime RouillerView Answer on Stackoverflow
Solution 3 - asp.net MvcmcbView Answer on Stackoverflow
Solution 4 - asp.net MvcSimon_WeaverView Answer on Stackoverflow