新 ASP.NET MVC 6 标识中 AspNetUsers table 中的 ConcurrencyStamp 列的用途是什么?
What is the purpose of the ConcurrencyStamp column in the AspNetUsers table in the new ASP.NET MVC 6 identity?
新的 ASP.NET MVC 6 标识中 AspNetUsers
table 中的 ConcurrencyStamp
列的用途是什么?
这是 AspNetUsers
table 的数据库模式:
它也在 AspNetRoles
table:
我记得它不存在于 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();
但是这个文档不足以让我了解它在哪些情况下使用。
/// <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();
基本上,见其名。用于标识数据当前版本的标记。如果您更改它,邮票也会更改。
所以如果两个并发更新同时进来,它们必须有相同的标记,否则其中一个应该被丢弃。
因此得名 ConcurrencyStamp
。
跟进 Maxime 的回复:
如果您查看 OnModelCreating() 方法中 IdentityDbContext 的实现,您会发现:
builder.Entity<TUser>(b =>
{
....
b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
....
并且在 UserStore.UpdateAsync(...)-方法中:
Context.Update(user);
try
{
await SaveChanges(cancellationToken);
}
catch (DbUpdateConcurrencyException)
{
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
因此,它确实做了它应该做的事情:防止对用户对象进行并发更新。该令牌仅在 ASP 身份 EntityFramework 模块中使用 "under the hood"。基本上,如果发生一个用户对象的并发更新,数据库上下文会抛出 DbUpdateConcurrencyException。
作为名称状态,用于防止并发更新冲突。
例如,数据库中有一个叫UserA
的Peter
2 管理员打开 UserA
的编辑器页面,想要更新此用户。
Admin_1
打开页面,看到用户叫Peter。
Admin_2
打开页面,看到用户叫 Peter(很明显)。
Admin_1
将用户名更新为 Tom,并保存数据。现在 UserA
在名为 Tom 的数据库中。
Admin_2
更新用户名为Thomas,并尝试保存。
如果没有 ConcurrencyStamp 会发生什么,Admin_1 的更新将被 Admin_2 的更新覆盖。
但是由于我们有 ConcurrencyStamp
,当 Admin_1
/Admin_2
加载页面时,就会加载图章。更新数据时,此戳记也会更改。
所以现在第 5 步将是系统抛出异常,告诉 Admin_2 该用户已经更新,因为他 ConcurrencyStamp
与他加载的不同。
认识到这实际上是一个 数据层特征 也很重要。 Identity defines the column as being a concurrency column 的架构,但实际上并未使用它。
Identity 代码库内部没有任何逻辑 - 只有当 EFCore 真正去保存它时它才会启动。
https://docs.microsoft.com/en-us/ef/core/modeling/concurrency
EF Code First - IsConcurrencyToken()
新的 ASP.NET MVC 6 标识中 AspNetUsers
table 中的 ConcurrencyStamp
列的用途是什么?
这是 AspNetUsers
table 的数据库模式:
它也在 AspNetRoles
table:
我记得它不存在于 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();
但是这个文档不足以让我了解它在哪些情况下使用。
/// <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();
基本上,见其名。用于标识数据当前版本的标记。如果您更改它,邮票也会更改。
所以如果两个并发更新同时进来,它们必须有相同的标记,否则其中一个应该被丢弃。
因此得名 ConcurrencyStamp
。
跟进 Maxime 的回复:
如果您查看 OnModelCreating() 方法中 IdentityDbContext 的实现,您会发现:
builder.Entity<TUser>(b =>
{
....
b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
....
并且在 UserStore.UpdateAsync(...)-方法中:
Context.Update(user);
try
{
await SaveChanges(cancellationToken);
}
catch (DbUpdateConcurrencyException)
{
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
因此,它确实做了它应该做的事情:防止对用户对象进行并发更新。该令牌仅在 ASP 身份 EntityFramework 模块中使用 "under the hood"。基本上,如果发生一个用户对象的并发更新,数据库上下文会抛出 DbUpdateConcurrencyException。
作为名称状态,用于防止并发更新冲突。
例如,数据库中有一个叫UserA
的Peter
2 管理员打开 UserA
的编辑器页面,想要更新此用户。
Admin_1
打开页面,看到用户叫Peter。Admin_2
打开页面,看到用户叫 Peter(很明显)。Admin_1
将用户名更新为 Tom,并保存数据。现在UserA
在名为 Tom 的数据库中。Admin_2
更新用户名为Thomas,并尝试保存。
如果没有 ConcurrencyStamp 会发生什么,Admin_1 的更新将被 Admin_2 的更新覆盖。
但是由于我们有 ConcurrencyStamp
,当 Admin_1
/Admin_2
加载页面时,就会加载图章。更新数据时,此戳记也会更改。
所以现在第 5 步将是系统抛出异常,告诉 Admin_2 该用户已经更新,因为他 ConcurrencyStamp
与他加载的不同。
认识到这实际上是一个 数据层特征 也很重要。 Identity defines the column as being a concurrency column 的架构,但实际上并未使用它。
Identity 代码库内部没有任何逻辑 - 只有当 EFCore 真正去保存它时它才会启动。
https://docs.microsoft.com/en-us/ef/core/modeling/concurrency
EF Code First - IsConcurrencyToken()