新しいASP.NET MVC 6 IDのConcurrencyStamp
テーブルのAspNetUsers
列の目的は何ですか?
これは、AspNetUsers
テーブルのデータベーススキーマです。
AspNetRoles
テーブルにもあります。
覚えているように、ASP.NET MVC 5 IDにはありませんでした。
私がこれまで気づいたことは、次のコードで定義されているように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();
しかし、このドキュメントでは、どの状況で使用されているかを理解するには不十分です。
名前の状態として、並行性更新の競合を防ぐために使用されます。
たとえば、データベース2にPeterという名前のUserAがいて、管理者2人がUserAのエディターページを開いて、このユーザーを更新したいとします。
ConcurrencyStampがない場合、Admin_1の更新はAdmin_2の更新によって上書きされます。しかし、ConcurrencyStampがあるため、Admin_1/Admin_2がページをロードすると、スタンプがロードされます。データを更新すると、このスタンプも変更されます。したがって、ステップ5は、ConcurrencyStampがロードしたものとは異なるため、このユーザーが既に更新されていることをAdmin_2に通知するシステムスロー例外です。
/// <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();
基本的に、名前が付けられているとおりに表示します。データの現在のバージョンを識別するために使用されるスタンプ。変更すると、スタンプも変更されます。
したがって、2つの同時更新が同時に発生した場合、それらは同じスタンプを持っているか、そのうちの1つを破棄する必要があります。
したがって、名前は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 Identity EntityFrameworkモジュールで「内部」で使用されます。基本的に、1つのユーザーオブジェクトの同時更新が発生すると、DBコンテキストはDbUpdateConcurrencyExceptionをスローします。
また、これが実際にEF Core機能であることを理解することも重要です。Identityのスキーマは、同時実行列として使用される列を定義するだけですが、最終的にはそれを必要とせず、内部で使用しません。
比較ロジックはありませんinsideIdentity codebase-EFCoreが実際にそれを保存するときだけが起動します。
https://docs.Microsoft.com/en-us/ef/core/modeling/concurrency