新ASP.NET MVC 6标识中AspNetUsers表中ConcurrencyStamp列的用途是什么?

Nik*_*tov 43 asp.net-mvc concurrency identity database-schema asp.net-core-mvc

新ASP.NET MVC 6标识中表中ConcurrencyStamp列的用途是什么AspNetUsers

这是AspNetUsers表的数据库模式:

在此输入图像描述

它也在AspNetRoles表中:

在此输入图像描述

我记得在ASP.NET MVC 5中没有它.

到目前为止我注意到它似乎有GUID值,因为它使用以下代码定义:

/// <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();
Run Code Online (Sandbox Code Playgroud)

但是这个文档不足以让我理解它在哪种情况下使用.

Ste*_*.Xi 59

作为名称状态,它用于防止并发更新冲突.

例如,在数据库中有一个名为Peter的UserA 2管理员打开UserA的编辑器页面,想要更新该用户.

  1. Admin_1打开了该页面,看到用户名为Peter.
  2. Admin_2打开了该页面,看到用户名叫Peter(显然).
  3. Admin_1将用户名更新为Tom,并保存数据.现在,db中的UserA名为Tom.
  4. Admin_2将用户名更新为Thomas,并尝试保存.

如果没有ConcurrencyStamp会发生什么,Admin_1的更新将覆盖Admin_1的更新.但由于我们有ConcurrencyStamp,当Admin_1/Admin_2加载页面时,会加载戳记.更新数据时,此标记也将更改.所以现在第5步将是系统抛出异常,告诉Admin_2该用户已经更新,因为他的ConcurrencyStamp与他加载的不同.


Max*_*ler 12

从源代码本身

    /// <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();
Run Code Online (Sandbox Code Playgroud)

基本上,看它命名.用于标识当前数据版本的戳记.如果你改变它,那么印章也是如此.

因此,如果两个并发更新同时进入,则它们必须具有相同的标记,否则应丢弃其中一个.

因此,名字,ConcurrencyStamp.

  • “两个并发更新......必须具有相同的标记”不正确/完整。任何更新都必须与存储中的行具有相同的戳记。 (3认同)

Sim*_*ver 9

同样重要的是要意识到这实际上是一个数据层功能。Identity 的架构将该列定义为并发列,但实际上并未使用它。

Identity 代码库内部没有任何逻辑——只有当 EFCore 真正去保存它时,它才会启动。

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

EF 代码优先 - IsConcurrencyToken()


小智 5

跟进Maxime的回复:

如果您在OnModelCreating()方法中查看IdentityDbContext的实现,则会发现:

builder.Entity<TUser>(b =>
{
....
    b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
....
Run Code Online (Sandbox Code Playgroud)

并在UserStore.UpdateAsync(...)方法中:

    Context.Update(user);
    try
    {
        await SaveChanges(cancellationToken);
    }
    catch (DbUpdateConcurrencyException)
    {
        return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
    }
Run Code Online (Sandbox Code Playgroud)

因此,它确实可以实现预期的功能:防止对用户对象进行并发更新。令牌仅在ASP Identity EntityFramework模块中“在后台”使用。基本上,如果发生一个用户对象的并发更新,则数据库上下文将引发DbUpdateConcurrencyException。