68 votes

Dois-je activer ou désactiver les proxies dynamiques avec entity framework 4.1 et MVC3 ?

Quelqu'un pourrait-il me donner des conseils ou m'indiquer des blogs/articles qui pourraient m'aider à prendre cette décision ? Les proxies me semblent très étrangers et j'hésite à les utiliser. J'aime la possibilité de contrôler le chargement paresseux en utilisant des propriétés virtuelles dans mon modèle, mais c'est à peu près tous les avantages que je peux voir. Mon application est une simple application web MVC et je n'ai pas besoin de mettre en place des crochets dans le contexte pour savoir quand les entités subissent un changement d'état.

Quoi qu'il en soit, voici ma liste très limitée d'avantages et d'inconvénients pour le moment, faites-moi savoir si je suis à côté de la plaque.

Pour

  • Lors de la sauvegarde ou de la mise à jour, le message "Appliquer les modifications" ne correspond à rien.
  • La configuration du Lazy-Loading est très simple.

Cons

  • Je n'ai jamais utilisé de proxy auparavant pour mes entités, c'est un changement de d'approche qui me met mal à l'aise, ainsi que les autres membres de l'équipe. membres de l'équipe.
  • C'est difficile à déboguer.
  • Nécessite du code supplémentaire si je veux sérialiser/dé-sérialiser
  • Lors de la sauvegarde ou de la mise à jour, le proxy doit être le même objet que celui qui a été récupéré dans le contexte.

102voto

Slauma Points 76561

Si l'on parle de proxies dynamiques dans EF, il faut en distinguer deux types différents :

  • Proxies pour le chargement paresseux
  • Proxies pour le suivi des changements

En général, un proxy de suivi des modifications peut également servir de proxy pour le chargement paresseux. L'inverse n'est pas vrai. En effet, les exigences pour les mandataires de suivi des modifications sont plus élevées, notamment todo les propriétés - également les propriétés scalaires - doivent être virtual . Pour le chargement paresseux, il suffit que les propriétés de navigation soient virtual .

Le fait qu'un proxy de suivi des modifications permette également de tirer parti du chargement paresseux est la principale raison pour laquelle le DbContext dispose de cet indicateur de configuration :

DbContext.Configuration.LazyLoadingEnabled

Ce drapeau est vrai par défaut. En lui donnant la valeur false désactive le chargement paresseux même si des proxies sont créés. Ceci est particulièrement important si vous travaillez avec des proxies de suivi des modifications mais que vous ne voulez pas utiliser ces proxies pour le chargement paresseux également.

L'option ...

DbContext.Configuration.ProxyCreationEnabled

... désactive complètement la création de proxy - pour le suivi des changements et le chargement paresseux également.

Ces deux drapeaux n'ont de sens que si vos classes d'entités répondent aux exigences de création de proxies de suivi des modifications ou de chargement paresseux.

Maintenant, vous connaissez l'utilité des proxies dynamiques à chargement paresseux. Alors, pourquoi utiliser des proxies dynamiques de suivi des modifications ?

En fait, la seule raison que je connaisse est performance . Mais c'est une raison très forte. Si l'on compare le suivi des modifications basé sur les instantanés avec le suivi des modifications basé sur les mandataires, la différence de performance est énorme - d'après mes mesures, un facteur de 50 à 100 est réaliste (d'après une méthode qui nécessitait environ une heure pour 10000 entités avec le suivi des modifications basé sur les instantanés et 30 à 60 secondes après avoir rendu toutes les propriétés virtuelles pour activer les mandataires de suivi des modifications). Cela devient un facteur important si vous avez une application qui traite et modifie de nombreuses entités (disons plus de 1000). Dans une application web où il est possible que vous n'ayez que des opérations de création/modification/suppression sur des entités uniques dans une requête web, cette différence n'est pas si importante.

Dans presque toutes les situations, vous pouvez tirer parti du chargement rapide ou explicite pour atteindre le même objectif si vous ne voulez pas travailler avec des mandataires de chargement paresseux. Les performances du chargement paresseux basé sur un proxy ou du chargement explicite basé sur un non-proxy sont les mêmes, car la même requête est effectuée lors du chargement des propriétés de navigation - dans le premier cas, c'est le proxy qui effectue la requête, dans le second, c'est votre code écrit à la main. Ainsi, vous pouvez vivre sans les proxys de chargement paresseux sans perdre beaucoup.

Mais si vous souhaitez obtenir des performances raisonnables pour traiter un très grand nombre d'entités, il n'y a pas d'autre solution que de changer les mandataires de suivi - à part l'utilisation de l'option EntityObject dans EF 4.0 (ce n'est pas une option dans EF 4.1 car c'est interdit lorsque l'on utilise des entités dérivées DbContext ) ou ne pas utiliser du tout Entity Framework.

Edit (mai 2012)

En attendant, j'ai appris qu'il y a des situations où Proxies de suivi des changements ne sont pas plus rapides, voire moins performants, par rapport au suivi basé sur les instantanés.

En raison de ces complications lors de l'utilisation de proxies de suivi des modifications, il est préférable d'utiliser par défaut le suivi des modifications basé sur les instantanés et d'utiliser les proxies avec précaution (après avoir effectué quelques tests) uniquement dans les situations où des performances élevées sont requises et où ils s'avèrent plus rapides que le suivi des modifications basé sur les instantanés.

15voto

duoct Points 101

Pour tous ceux qui utilisent Entity Framework 5, n'oubliez pas de consulter le site Web de la Commission européenne. Considérations sur les performances article. Sections 5 NoTracking Queries y 8 Loading Related Entities offre les informations dont vous avez besoin pour prendre une décision éclairée. A la vôtre.

2voto

Je vous suggère de ne PAS utiliser de mandataires. La création de proxy dynamique casse ou crée des complications pour les composants qui dépendent de la vérification de type à l'exécution.

Automapper, par exemple, lancera une erreur de correspondance de type / erreur de type inattendue pendant l'exécution, car vos entités auront des types de proxy générés dynamiquement pendant l'exécution, et non les types que vous avez transmis lors de la configuration de l'automapping.

0voto

Chriss Points 61

Bien que les proxies dynamiques présentent quelques caractéristiques intéressantes, ils peuvent en réalité créer un grand nombre de bogues étranges et obscurs.

Par exemple, j'ai gardé une variable privée d'une entité dans une de mes classes (elle implémentait un processus batch) et je bouclais sur quelques millions d'enregistrements, les traitant et les insérant par lots, recréant le contexte de données tous les n enregistrements pour nettoyer la mémoire. Bien que je n'aie JAMAIS utilisé la variable privée, EF la liait à mes nouveaux objets (il y avait une référence par le biais d'une propriété de navigation) même si je ne faisais que paramétrer l'Id de la référence.

Ainsi, tous les objets sont restés en mémoire pendant toute la durée du processus. J'ai dû utiliser AsNoTracking et désactiver les proxies pour que le processus fonctionne comme prévu et que la mémoire et les performances reviennent à des niveaux normaux. Gardez à l'esprit que les proxies font également référence au contexte qui les a créés et qu'ils peuvent garder en mémoire d'énormes graphiques d'entités, ce qui est presque impossible à déboguer.

Je pense donc que vous devriez désactiver les proxies de manière globale et les activer dans de petits morceaux de code contenus. Il est très dangereux et impossible de déboguer de tels problèmes, surtout lorsque de grandes équipes codent.

Le suivi des changements est intéressant, il pourrait justifier l'utilisation dans certains endroits. Le chargement paresseux peut être un énorme problème de performance et de sérialisation, sauf si vous savez ce que vous faites. Je préfère le chargement rapide ou explicite à tout moment.

0voto

J'utilise Automapper 4.2.1. La nouvelle version n'a pas de DynamicMap

var parents = parentsRepo.GetAll().ToList();
Mapper.CreateMap<Parent,ParentDto>();
var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);

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