13 votes

EF Code First : est-il bon d'appeler DetectChanges juste avant SaveChanges ?

J'ai lu quelques articles ( article1 , article2 ) à propos d'Entity Framework qu'il appelle DetectChanges de nombreuses fois, ce qui le rend très lent lorsqu'il travaille avec de grandes quantités de données.

Puis-je, par exemple, désactiver le autoDetectChanges quand j'initialise le contexte, et que j'appelle juste DetectChanges() avant d'appeler .SaveChanges() ?

Le contexte reconnaîtra-t-il les entités insérées/modifiées/supprimées ?

var _dbContext = new ProjectContext();
_dbContext.Configuration.AutoDetectChangesEnabled = false;

// add/edit/delete entities

_dbContext.ChangeTracker.DetectChanges();
_dbContext.SaveChanges();

Cette approche devrait-elle fonctionner ? ou pourrait-elle créer des bugs cachés ?

21voto

Slauma Points 76561

Arthur Vickers définit une règle lorsque DetectChanges n'a pas besoin d'être appelé (même pas avant que SaveChanges ) dans cet article de blog :

Aucun appel au code EF ne laissera le contexte dans un état où DetectChanges doit être appelé s'il ne l'a pas été auparavant. avant.

Concernant Ajouter y Supprimer il s'agit de méthodes "code EF" car vous appelez soit Add ou Delete ou vous définissez l'état de context.Entry(entity).State à Added ou Deleted . Ainsi, si vous souhaitez simplement parcourir en boucle un ensemble d'entités et les ajouter ou les supprimer, vous n'avez pas besoin d'appeler la commande DetectChanges du tout.

Concernant Editar elle est, je crois, un peu plus subtile. Lorsque vous mettez à jour des entités en utilisant soit...

context.Entry(entity).CurrentValues.SetValues(someObject);

...ou en utilisant l'API de propriété de DbContext ...

context.Entry(entity).Property(e => e.SomeProperty).CurrentValue = someValue;

...alors vous n'avez pas besoin DetectChanges (même pas avant SaveChanges ) soit parce qu'il s'agit à nouveau d'appels au "code EF".

Si vous changez juste les valeurs des propriétés d'une entité comme...

entity.SomeProperty = someValue;

...puis la deuxième règle dans le même article de blog lié ci-dessus s'applique :

Chaque fois que du code non-EF modifie une valeur de propriété d'une entité ou d'un ou d'un objet complexe, il peut être nécessaire d'appeler DetectChanges.

Et je pense que vous n'avez besoin en fait que d'un seul appel à DetectChanges avant SaveChanges si il suffit de passer en boucle certaines entités, de les charger ou de les attacher au contexte et de modifier certaines valeurs de propriétés (scalaires et complexes).

Si vous faites des choses plus complexes (peut-être des changements de relation ? ou autre chose ?), votre approche pourrait ne plus être sûre car

  1. AutoDetectChanges ne serait pas implémenté de la manière dont il l'est et appelé dans de nombreuses méthodes EF s'il n'était nécessaire qu'une seule fois juste avant SaveChanges

  2. il est mentionné dans le même article de blog encore une fois que

    Si le code apporte des modifications aux propriétés des entités au lieu de simplement appeler Add ou Attach, alors, selon la règle 2, DetectChanges devra être appelé, au moins dans le cadre de SaveChanges et éventuellement également avant alors.

    (Mise en évidence par moi)

Malheureusement, je ne connais pas d'exemple de code qui montrerait que l'on appelle DetectChanges à des stades plus précoces que juste avant SaveChanges est nécessaire. Mais en raison du point 1 ci-dessus, je suis sûr que de tels exemples existent.

-1voto

MMB Points 11

L'un des principaux problèmes que l'on peut résoudre en DetectChanges est de persister les données dans EF quand nous avons ManyToMany et AutoDetectChanges=false .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X