Comment détacher des objets dans Entity Framework Code First?

Réponses:

156

Si vous souhaitez détacher un objet existant, suivez les conseils de @ Slauma. Si vous souhaitez charger des objets sans suivre les modifications, utilisez:

var data = context.MyEntities.AsNoTracking().Where(...).ToList();

Comme mentionné dans le commentaire, cela ne détachera pas complètement les entités. Ils sont toujours attachés et le chargement différé fonctionne mais les entités ne sont pas suivies. Cela doit être utilisé par exemple si vous souhaitez charger une entité uniquement pour lire des données et que vous ne prévoyez pas de les modifier.

Ladislav Mrnka
la source
3
@Ladislav: C'est en effet probablement ce que voulait dire le codeur Lol. Je n'ai jamais utilisé et pensé à cette méthode bien que je charge souvent des listes d'objets et supprime le contexte à la fois, quelque chose comme using(ctx){ return ctx....ToList(); }. Dans de tels cas, l'utilisation AsNoTracking()aurait beaucoup de sens car j'économiserais de remplir le contexte de l'objet inutilement. Je suppose que cela aurait probablement un avantage en termes de performances et de consommation de mémoire, en particulier pour les grandes listes, non?
Slauma
1
@Slauma: Oui, cela a des avantages en termes de performances. C'est en fait pourquoi cette méthode existe. L'utilisation de cette approche dans l'API ObjectContext est un peu plus compliquée.
Ladislav Mrnka
2
Est-ce que cela désactive le chargement paresseux?
Shawn Mclean
3
En fait, cela ne désactivera pas le chargement différé, cela désactivera uniquement le suivi des modifications et améliorera les performances = l'entité est toujours attachée. Je l'ai trouvé après avoir répondu à cette question, vous devriez donc marquer celle de @ Slauma comme une réponse valide.
Ladislav Mrnka
1
C'est ce que je veux. Je veux un chargement paresseux et la possibilité de ne modifier qu'une entité détachée.
Shawn Mclean
255

Ceci est une option:

dbContext.Entry(entity).State = EntityState.Detached;
Slauma
la source
3
Puis-je faire cela lors de la récupération d'objets qui renvoie un IQueryable?
Shawn Mclean
1
@Lol coder: Je ne sais pas si je vous comprends bien, mais entitydoit être un objet matérialisé d'un type qui fait partie de vos classes de modèle (Personne, Client, Commande, etc.). Vous ne pouvez pas passer directement un IQueryable <T> dans dbContext.Entry(...). Est-ce la question que vous vouliez dire?
Slauma
9
@EladBenda: Cela dépend. Si vous souhaitez détacher un objet qui est déjà attaché au contexte, définissez l'état sur Detached. Si vous souhaitez charger des entités à partir de la base de données sans les attacher du tout au contexte (pas de suivi des modifications), utilisez AsNoTracking.
Slauma
1
J'ai trouvé un problème intéressant avec cette méthode. Même si l'entité peut être une classe proxy, le chargement différé ne fonctionnera pas une fois que vous aurez changé son état en Detached.
kjbartel
4
@kjbartel: c'est le comportement attendu, puisque l'entité n'a aucun lien avec le contexte.
Ricardo Souza