web-dev-qa-db-fra.com

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

Quelqu'un pourrait-il offrir des conseils ou signaler des blogs/articles pouvant aider à prendre cette décision? Les procurations me semblent très étrangères et j'hésite à les utiliser. J'aime la possibilité de contrôler le chargement différé à l'aide de 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 raccorder de points d'ancrage au contexte lorsque 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 ne suis pas à la hauteur de la situation. 

Avantages

  • Sur "Enregistrer" ou "Mettre à jour", je suis transparente avec "Apply'Changes"
  • La configuration de chargement paresseux est très facile.

Les inconvénients

  • Jamais utilisé auparavant de proxy pour mes entités, c’est un changement d’approche Qui me semble inconfortable pour moi-même et les membres de l’équipe
  • Difficile à déboguer. 
  • Nécessite du code supplémentaire si je veux sérialiser/désérialiser
  • Sur "Enregistrer" ou "Mettre à jour", le proxy doit être le même objet que celui qui a été extrait du contexte.
66
matt_dev

Si vous parlez de proxys dynamiques dans EF, vous devez distinguer deux types:

  • Des procurations pour le chargement paresseux
  • Des procurations pour le suivi des modifications

Habituellement, un proxy de suivi des modifications peut également servir de proxy pour un chargement différé. L'inverse n'est pas vrai. En effet, les exigences relatives aux mandataires de suivi des modifications sont plus strictes, en particulier les propriétés tout, ainsi que les propriétés scalaires, doivent être virtual. Pour un chargement différé, il suffit que les propriétés de navigation soient virtual.

Le fait qu'un proxy de suivi des modifications permette toujours de tirer parti du chargement différé est la principale raison pour laquelle DbContext possède cet indicateur de configuration:

DbContext.Configuration.LazyLoadingEnabled

Cet indicateur est vrai par défaut. Si vous le définissez sur false, le chargement différé est désactivé même si des mandataires sont créés. Ceci est particulièrement important si vous travaillez avec des mandataires de suivi des modifications mais que vous ne souhaitez pas utiliser ces mandataires pour le chargement différé.

L'option ...

DbContext.Configuration.ProxyCreationEnabled

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

Les deux indicateurs n'ont de signification que si vos classes d'entité remplissent les conditions pour créer un proxy de suivi des modifications ou de chargement paresseux.

Maintenant, vous connaissez l’utilité des serveurs proxy dynamiques à chargement paresseux. Alors, pourquoi devrait-on utiliser des proxys de suivi des modifications dynamiques?

En fait, la seule raison pour laquelle je suis au courant est performance. Mais c'est une très forte raison. Comparer le suivi des modifications basé sur les instantanés avec le changement basé sur les procurations est énorme - d'après mes mesures, un facteur de 50 à 100 est réaliste (tiré d'une méthode qui nécessitait environ une heure pour 10000 entités avec un suivi des modifications basé sur des 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 plusieurs entités (disons plus de 1000). Dans une application Web où vous ne possédez éventuellement que des opérations Créer/Modifier/Supprimer sur des entités uniques dans une demande Web, cette différence est sans importance.

Dans presque toutes les situations, vous pouvez utiliser le chargement rapide ou explicite pour atteindre le même objectif si vous ne voulez pas travailler avec des proxies de chargement paresseux. Les performances pour le chargement différé basé sur le proxy ou le chargement explicite non basé sur le proxy sont identiques, car la même requête se produit lorsque les propriétés de navigation sont chargées: dans le premier cas, le proxy effectue la requête, dans le second cas, votre code manuscrit. Ainsi, vous pouvez vivre sans charger par procuration des proxies sans perdre trop.

Mais si vous souhaitez que les performances soient raisonnables pour traiter de nombreuses entités, il n'y a pas d'alternative aux mandataires de suivi des modifications - mis à part l'utilisation d'entités dérivées EntityObject dans EF 4.0 (option non disponible dans EF 4.1 car elle est interdite lorsque vous utilisez DbContext) ou de ne pas utiliser Entity Framework. du tout.

Edit (mai 2012)

Dans l'intervalle, j'ai appris qu'il existait des situations dans lesquelles les mandataires de suivi des modifications n'étaient pas plus rapides ni même pires en termes de performances par rapport au suivi basé sur des instantanés.

En raison de ces complications lors de l’utilisation de serveurs mandataires de suivi des modifications, la méthode recommandée consiste à utiliser le suivi des modifications basé sur des instantanés par défaut et à utiliser les mandataires avec précaution (après avoir effectué certains tests) uniquement dans des situations exigeant des performances élevées et s’avérant être plus rapides que les outils instantanés. changement de suivi.

101
Slauma

Si vous utilisez Entity Framework 5, consultez l’article Considérations sur les performances . Sections 5 NoTracking Queries et 8 Loading Related Entities offrent les informations dont vous avez besoin pour prendre une décision éclairée. À votre santé.

15
duoct

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

Automapper, par exemple, générera une erreur d'incompatibilité de type/type inattendue lors de l'exécution, car vos entités auront des types de proxy générés de manière dynamique lors de l'exécution, et non des types que vous avez transmis lors de la configuration de l'auto-mapping.

2
Daffy Punk

Utilisez 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);

Bien que les proxies dynamiques aient quelques fonctionnalités intéressantes, elles peuvent en réalité créer beaucoup de bogues étranges et obscurs.

Par exemple, une variable privée d’une entité dans une de mes classes (il implémentait un traitement par lots) a été conservée et j’ai parcouru quelques millions d’enregistrements, les ai traités et insérés par lots, recréant le contexte de données tous les nettoyer la mémoire. Bien que je n'utilise JAMAIS la variable privée, EF la liait à mes nouveaux objets (il y avait une référence via une propriété de navigation) même si je ne définissais que l'ID de référence. 

Cela a fait que tous les objets sont restés en mémoire pendant toute la durée d'exécution du processus. J'ai dû utiliser AsNoTracking et désactiver les proxys afin que le processus fonctionne comme prévu et que la mémoire et les performances reviennent à des niveaux normaux. N'oubliez pas que les mandataires font également référence au contexte qui les a créés et que cela peut garder en mémoire d'énormes graphiques d'entités, il est presque impossible de le déboguer.

Donc, je pense que vous devriez désactiver globalement les proxys et les activer dans des petits morceaux de code. Il est très dangereux et impossible de déboguer de tels problèmes, en particulier lorsque vous devez coder de grandes équipes. 

Le suivi des modifications est agréable, il peut justifier l’utilisation dans certains endroits ..__ Le chargement paresseux peut être un énorme problème de performances et de sérialisation à moins que vous ne sachiez ce que vous faites. Je préfère un chargement empressé ou explicite à tout moment.

0
Chriss