web-dev-qa-db-fra.com

Option de fusion Entity Framework ne présentant pas de mauvaises performances

J'ai un comportement étrange en essayant d'exécuter une requête déclarant ObjectQuery MergeOption à "NoTracking", dans ce cas, le cadre d'entité ne doit attacher aucune entité et ne pas créer l'ObjectStateEntry relatif pour suivre l'état de l'entité.

Le problème est qu'au lieu d'augmenter les performances, cela empire, la même requête prend environ 10 secondes avec l'option de fusion par défaut (c'est-à-dire AppendingOnly) et plus les 1 minutes si j'essaie de spécifier notracking

Quelqu'un at-il une explication à cela ??

49
MaRuf

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

Cela signifie que potentiellement beaucoup plus d'objets - beaucoup avec la même clé - seront matérialisés.

Exemple: supposons que vous ayez une entité User avec une collection Roles comme propriété de navigation. Supposons également que vous ayez 1 million d'utilisateurs dans la base de données et que tous les utilisateurs soient dans les mêmes 10 rôles, c'est-à-dire 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'objets matérialisés et instanciés dépend de l'option de fusion:

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

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

La matérialisation des objets est classée avec coûts de performance "modérés" :

Opération: Matérialisation des objets
Coût relatif: modéré
Fréquence: une fois pour chaque objet renvoyé par une requête.

Commentaires: Processus de lecture de l'objet DbDataReader renvoyé et de création d'objets et de définition de valeurs de propriété basées sur les valeurs de chaque instance de la classe DbDataRecord. Si l'objet existe déjà dans ObjectContext et que la requête utilise les options de fusion AppendOnly ou PreserveChanges, cette étape ne correspond pas affecter 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 performances en bénéficient du suivi des modifications désactivées sont détruites par les inconvénients de la gestion des identités désactivées et de la matérialisation multipliée des objets.

146
Slauma