Entity Framework mergeoption ne détecte pas les mauvaises performances

J’ai un comportement étrange en essayant d’exécuter une requête déclarant ObjectQuery MergeOption à “NoTracking”, dans ce cas, la structure d’entité ne doit associer aucune entité et ne pas créer l’ObjectStateEntry relatif pour suivre l’état d’une entité.

Le problème est que, au lieu d’augmenter les performances, la situation s’aggrave, la même requête prend 10 secondes avec l’option de fusion par défaut (AppendingOnly) et plus de 1 minute si je tente de spécifier le suivi.

Est-ce que quelqu’un a une explication à cela?

Si vous désactivez le suivi des modifications en définissant l’option de fusion NoTracking , vous économisez les coûts de performance liés à l’attachement d’objects aux contextes, mais vous perdez également la gestion des identités.

Cela signifie que potentiellement beaucoup plus d’objects – beaucoup avec la même clé – seront matérialisés.

Exemple: supposons que vous ayez une entité User avec une collection de Roles tant que propriété de navigation. Supposons également que la firebase database compte 1 million d’utilisateurs et que tous les utilisateurs occupent les mêmes rôles, c.-à-d. Que chaque utilisateur possède une collection de rôles avec 10 éléments. Si vous exécutez la requête suivante …

 var users = context.Users.Include("Roles").ToList(); 

… le nombre d’objects matérialisés et instanciés dépend de l’option de fusion:

  • Si vous n’utilisez pas NoTracking vous aurez 1.000.010 objects en mémoire, à savoir 1 million d’utilisateurs, mais seulement 10 rôles car le mappage d’identité garantira qu’un seul rôle par clé est matérialisé et associé au contexte. Les mêmes 10 instances de rôle sont utilisées pour la collection de Roles tous les utilisateurs.

  • Si vous utilisez NoTracking , EF n’attachera pas d’objects au contexte. La gestion des identités est donc désactivée et vous aurez 11 000 000 d’objects en mémoire: 1 million d’utilisateurs et 10 instances de rôles par utilisateur, soit 10 millions d’objects de rôle. Ainsi, vous avez plus de 10 fois plus d’objects matérialisés que lorsque les objects sont attachés au contexte.

La matérialisation d’object est classée avec des coûts de performance “modérés” :

Opération: matérialiser les objects
Coût relatif: modéré
Fréquence: une fois pour chaque object renvoyé par une requête.

Commentaires: Processus de lecture de l’object DbDataReader renvoyé et de création d’objects et de définition de valeurs de propriétés basées sur les valeurs de chaque instance de la classe DbDataRecord. Si l’object existe déjà dans ObjectContext et que la requête utilise les options de fusion AppendOnly ou PreserveChanges , cette étape n’affecte pas les performances.

En d’autres termes: si la requête utilise l’option de fusion NoTracking , cette étape affecte les performances et il est possible que les avantages des performances du suivi des modifications désactivées soient détruits par les inconvénients de la gestion des identités désactivée et de la matérialisation d’objects multipliés.