新ASP.NET MVC 6标识中表中ConcurrencyStamp
列的用途是什么AspNetUsers
?
这是AspNetUsers
表的数据库模式:
它也在AspNetRoles
表中:
我记得在ASP.NET MVC 5中没有它.
到目前为止我注意到它似乎有GUID值,因为它使用以下代码定义:
////// A random value that must change whenever a user is persisted to the store /// public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString();
但是这个文档不足以让我理解它在哪种情况下使用.
作为名称状态,它用于防止并发更新冲突.
例如,在数据库中有一个名为Peter的UserA 2管理员打开UserA的编辑器页面,想要更新该用户.
Admin_1打开了该页面,看到用户名为Peter.
Admin_2打开了该页面,看到用户名叫Peter(显然).
Admin_1将用户名更新为Tom,并保存数据.现在,db中的UserA名为Tom.
Admin_2将用户名更新为Thomas,并尝试保存.
如果没有ConcurrencyStamp会发生什么,Admin_1的更新将覆盖Admin_1的更新.但由于我们有ConcurrencyStamp,当Admin_1/Admin_2加载页面时,会加载戳记.更新数据时,此标记也将更改.所以现在第5步将是系统抛出异常,告诉Admin_2该用户已经更新,因为他的ConcurrencyStamp与他加载的不同.
从源代码本身
///
/// A random value that should change whenever a role is persisted to the store
///
public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString();
基本上,看它命名.用于标识当前数据版本的戳记.如果你改变它,那么印章也是如此.
因此,如果两个并发更新同时进入,则它们必须具有相同的标记,否则应丢弃其中一个.
因此,名字,ConcurrencyStamp
.
跟进Maxime的回复:
如果您在OnModelCreating()方法中查看IdentityDbContext的实现,则会发现:
builder.Entity(b => { .... b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken(); ....
并在UserStore.UpdateAsync(...)方法中:
Context.Update(user); try { await SaveChanges(cancellationToken); } catch (DbUpdateConcurrencyException) { return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure()); }
因此,它确实可以实现预期的功能:防止对用户对象进行并发更新。令牌仅在ASP Identity EntityFramework模块中“在后台”使用。基本上,如果发生一个用户对象的并发更新,则数据库上下文将引发DbUpdateConcurrencyException。