Подтвердить что ты не робот

Какова цель столбца ConcurrencyStamp в таблице AspNetUsers в новом идентификаторе ASP.NET MVC 6?

Какова цель столбца ConcurrencyStamp в таблице AspNetUsers в новом идентификаторе ASP.NET MVC 6?

Это схема базы данных таблицы 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();

Но этой документации недостаточно для того, чтобы понять, в каких ситуациях она используется.

4b9b3361

Ответ 1

В качестве состояния имени он предотвращал конфликт concurrency.

Например, в базе данных есть UserA с именем Peter 2 администратора открывают страницу редактора UserA, хотят обновить этого пользователя.

  • Admin_1 открыл страницу и увидел пользователя под названием Peter.
  • Admin_2 открыл страницу и увидел пользователя с именем Peter (очевидно).
  • Admin_1 обновил имя пользователя Tom и сохранил данные. Теперь UserA в db с именем Tom.
  • Admin_2 обновил имя пользователя Томасу и попытался его сохранить.

Что произойдет, если обновление ConcurrencyStamp в Admin_1 не будет перезаписано обновлением Admin_2. Но поскольку у нас есть ConcurrencyStamp, когда Admin_1/Admin_2 загружает страницу, штамп загружается. При обновлении данных эта марка также будет изменена. Итак, теперь шаг 5 будет исключать системное исключение, сообщая Admin_2, что этот пользователь уже обновлен, поскольку он ConcurrencyStamp отличается от того, который он загрузил.

Ответ 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();

В принципе, посмотрите, как он называется. Штамп, который используется для идентификации текущей версии данных. Если вы измените его, то и печать.

Итак, если одновременно возникают два одновременных обновления, они должны иметь один и тот же штамп, или один из них должен быть отброшен.

Следовательно, имя, ConcurrencyStamp.

Ответ 3

Чтобы следить за ответом Maxime:

Если вы посмотрите на реализацию IdentityDbContext в методе OnModelCreating(), вы найдете:

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. В принципе, если возникает одновременное обновление одного пользовательского объекта, контекст БД выдает исключение DbUpdateConcurrencyException.

Ответ 4

Также важно понять, что на самом деле это функция EF Core, схема Identity просто определяет столбец при использовании в качестве столбца параллелизма, но в конечном итоге не требует его или не использует его внутри себя.

Внутри Identity codebase не существует логики сравнения, она только тогда, когда EFCore действительно идет, чтобы сохранить ее, что она запускает.

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

EF Code First - IsConcurrencyToken()