0
votes

Pourquoi Entity Framework tente-t-il de mettre à jour plusieurs lignes lorsque j'enregistre mes modifications?

J'ai la méthode ci-dessous et lorsque l'enregistrement des modifications est exécuté, Entity Framework essaie de mettre à jour plus d'une ligne? Même si je ne modifie qu'une date sur un seul enregistrement et que je récupère un enregistrement à modifier.

Erreur

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: l'opération de base de données devrait affecter 1 ligne (s) mais a en fait affecté 2 ligne (s). Les données peuvent avoir été modifiées ou supprimées depuis le chargement des entités.

Méthode

SET NOCOUNT ON;
UPDATE [Records_Coworkers] SET [StartDate] = @p0
WHERE [RecordID] = @p1 AND [CoworkerID] = @p2;
SELECT @@ROWCOUNT;

D'une manière ou d'une autre, lorsque la requête est exécutée, les paramètres doivent être mis à jour correctement, par exemple. Champ «IsActive». J'ai capturé la requête ci-dessous.

    public static async Task<HttpResult> PostRecordCoworkerStartDateAsync(MpidDbContext context, int id, RecordCoworker recordCoworker)
    {
        // just testing to see how many are returned
        int testCount = context.RecordsCoworkers.Where(m => m.Id == id && m.IsActive == true).ToList().Count();

        RecordCoworker recordCoworkerToUpdate = context.RecordsCoworkers.SingleOrDefault(m => m.Id == id && m.IsActive == true);

        recordCoworkerToUpdate.StartDate = recordCoworker.StartDate;

        try
        {
            await context.SaveChangesAsync();
        } catch(Exception ex)
        {
            var i = ex;
        }

        return HttpResult.NoContent;
    }

en gros, je veux juste mettre à jour le seul enregistrement où «IsActive» est vrai. Mais la requête, car elle supprime la propriété 'IsActive', essaiera de mettre à jour deux ou plusieurs lignes.


0 commentaires

3 Réponses :


0
votes

J'ai découvert pourquoi.

Dans mon entité, j'avais besoin d'ajouter un attribut de données à la propriété 'IsActive'

    [Required]
    [ConcurrencyCheck]
    public bool IsActive { get; set; }


0 commentaires

1
votes

Juste pour expliquer pourquoi:

  1. Vous demandez à la base de données pour tous les utilisateurs actifs avec l'ID spécifique et prenez le premier résultat.
  2. Entity Framework envoie la demande et matérialise le résultat dans un objet.
  3. Vous modifiez la propriété.
  4. Le cadre d'entité définira l'état de l'objet sur modifié.
  5. Vous appelez SaveChanges pour signaler à EF qu'il renvoie les modifications à la base de données.
  6. Comme on sait quel identifiant a l'objet, il est directement adressé dans l'instruction de mise à jour.

Ce sont deux opérations: SELECT et UPDATE . Celles-ci sont effectuées séparément car Entity Framework ne sait pas: que faites-vous entre-temps (jusqu'à ce que vous SaveChanges ) à l'entité?

Attribution [ConcurrencyCheck] à la propriété indique à Entity Framework qu'il devrait veiller à ce que , au moment de la UPDATE à IsActive SELECT UPDATE de la valeur de la propriété IsActive devrait être le même que pendant la SELECT . Lorsqu'il y a différentes applications écrivant dans cette base de données, cela garantit qu'aucune des autres applications n'a changé l'entité pendant la période entre SELECT et UPDATE .

Vous devez supprimer la ligne int testCount . Ou demandez-les comme non suivis.


0 commentaires

0
votes

Dans mon cas, l'erreur a été causée par l'absence de colonne d'identification réelle.

Ce que je croyais être un ID - et configuré dans Entity Framework avec l'attribut [Key] - avait des duplications dans la base de données, donc même je l'ai utilisé pour filtrer j'ai mis à jour plusieurs lignes.


0 commentaires