web-dev-qa-db-fra.com

Quel est l'objectif de la colonne ConcurrencyStamp de la table AspNetUsers dans la nouvelle identité ASP.NET MVC 6?

Quel est l'objectif de la colonne ConcurrencyStamp de la table AspNetUsers de la nouvelle identité ASP.NET MVC 6?

Voici le schéma de base de données de la table AspNetUsers:

 enter image description here

C'est aussi là dans la table AspNetRoles:

 enter image description here

Si je me souviens bien, l'identité ASP.NET MVC 5 n'y figurait pas.

Ce que j'ai remarqué jusqu'à présent, c'est qu'il semble avoir les valeurs GUID telles qu'elles sont définies avec le code suivant:

/// <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();

Mais cette documentation ne me suffit pas pour comprendre dans quelles situations elle est utilisée.

31
Nikolay Kostov

En tant que nom, il est utilisé pour éviter les conflits de mise à jour par accès simultané.

Par exemple, il y a un utilisateurA nommé Peter dans la base de données 2 administrateurs ouvrent la page d'édition de UserA et souhaitent mettre à jour cet utilisateur.

  1. Admin_1 a ouvert la page et a vu un utilisateur appelé Peter.
  2. Admin_2 a ouvert la page et a vu un utilisateur appelé Peter (évidemment).
  3. Admin_1 a mis à jour le nom d'utilisateur sur Tom et enregistre les données. Maintenant, UserA dans la base de données nommé Tom.
  4. Admin_2 a mis à jour le nom d'utilisateur sur Thomas et essayez de le sauvegarder.

Que se passerait-il s'il n'y avait pas de ConcurrencyStamp si la mise à jour de Admin_1 était remplacée par celle de Admin_2 . Mais puisque nous avons ConcurrencyStamp, lorsque Admin_1/Admin_2 charge la page, le tampon est chargé. Lors de la mise à jour des données, ce tampon sera également modifié . L’étape 5 consisterait donc maintenant en une exception système en indiquant à Admin_2 que cet utilisateur avait déjà été mis à jour, car ConcurrencyStamp est différent de celui qu’il a chargé.

44
Steven.Xi

À partir du code source lui-même

    /// <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();

En gros, voyez-le comme il est nommé. Un tampon utilisé pour identifier la version actuelle des données. Si vous le changez, le tampon l'est aussi.

Ainsi, si deux mises à jour simultanées arrivent en même temps, elles doivent avoir le même tampon ou l’un d’eux devrait être jeté. 

D'où le nom, ConcurrencyStamp

9
Maxime Rouiller

Pour donner suite à la réponse de Maxime: 

Si vous regardez l'implémentation d'IdentityDbContext dans la méthode OnModelCreating (), vous trouverez:

builder.Entity<TUser>(b =>
{
....
    b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
....

et dans la méthode UserStore.UpdateAsync (...):

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

Donc, il fait bien ce qu'il est censé faire: empêcher les mises à jour simultanées sur un objet utilisateur. Le jeton est simplement utilisé "sous le capot" dans le module ASP Identity EntityFramework. En gros, si une mise à jour simultanée d'un objet utilisateur se produit, le contexte de base de données lève l'exception DbUpdateConcurrencyException.

4
mcb

Il est également important de comprendre qu’il s’agit en fait d’une fonctionnalité EF Core, le schéma d’Identity définissant simplement la colonne à utiliser comme colonne de simultanéité, sans pour autant la demander ni l’utiliser en interne. 

Il n'y a pas de logique de comparaison en cours inside Identity codebase - c'est uniquement lorsque EFCore va réellement le sauvegarder qu'il entre en jeu.

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

EF Code First - IsConcurrencyToken ()

1
Simon_Weaver