Entity Framework et regroupement de connexions

.net ado.net connection-pooling database entity-framework

Question

J'ai récemment commencé à utiliser Entity Framework 4.0 dans mon application .NET 4.0 et je suis curieux de connaître certaines choses relatives à la mise en pool.

  1. Le regroupement des connexions, comme je le sais, est géré par le fournisseur de données ADO.NET, dans mon cas, celui du serveur MS SQL. Cela s’applique-t-il lorsque vous instanciez un nouveau contexte d’entités ( ObjectContext ), c’est-à-dire le new MyDatabaseModelEntities() paramètre?

  2. Quels sont les avantages et les inconvénients de a) créer un contexte d'entités globales pour l'application (c'est-à-dire une instance statique) ou b) de créer et d'exposer un contexte d'entités pour chaque opération / méthode donnée, avec un bloc using .

  3. Y a-t-il d'autres recommandations, meilleures pratiques ou approches communes pour certains scénarios que je devrais connaître?

Réponse acceptée

  1. Le regroupement de connexions est géré comme dans toute autre application ADO.NET. La connexion d'entité utilise toujours la connexion de base de données traditionnelle avec la chaîne de connexion traditionnelle. Je crois que vous pouvez désactiver le regroupement de connexions dans une chaîne de connexion si vous ne souhaitez pas l'utiliser. (en savoir plus sur le regroupement de connexions SQL Server (ADO.NET) )
  2. Ne jamais utiliser le contexte global. ObjectContext implémente en interne plusieurs modèles, notamment la carte d'identité et l'unité de travail. L'impact de l'utilisation du contexte global est différent selon le type d'application.
  3. Pour les applications Web, utilisez un seul contexte par demande. Pour les services Web, utilisez un seul contexte par appel. Dans WinForms ou une application WPF, utilisez un seul contexte par formulaire ou par présentateur. Il peut y avoir des exigences spéciales qui ne permettent pas d’utiliser cette approche mais dans la plupart des cas, cela suffit.

Si vous souhaitez savoir quel impact a le contexte d'objet unique pour l'application WPF / WinForm, consultez cet article . Il s’agit de NHibernate Session mais l’idée est la même.

Modifier:

Lorsque vous utilisez EF, il charge par défaut chaque entité une fois par contexte. La première requête crée une instance d'entité et la stocke en interne. Toute requête ultérieure nécessitant une entité avec la même clé renvoie cette instance stockée. Si les valeurs du magasin de données ont changé, vous recevez toujours l'entité avec les valeurs de la requête initiale. C'est ce qu'on appelle un modèle de carte d'identité . Vous pouvez forcer le contexte de l'objet à recharger l'entité, mais cela rechargera une seule instance partagée.

Toutes les modifications apportées à l'entité ne sont pas conservées jusqu'à ce que vous SaveChanges sur le contexte. Vous pouvez modifier plusieurs entités et les stocker simultanément. C'est ce qu'on appelle le modèle d'unité de travail . Vous ne pouvez pas indiquer de manière sélective quelle entité attachée modifiée vous souhaitez enregistrer.

Combinez ces deux modèles et vous verrez des effets intéressants. Vous n'avez qu'une seule instance d'entité pour toute l'application. Toutes les modifications apportées à l'entité affectent l'ensemble de l'application même si les modifications ne sont pas encore persistées (validées). Dans la plupart des cas, ce n'est pas ce que vous voulez. Supposons que vous ayez un formulaire d'édition dans l'application WPF. Vous travaillez avec l'entité et vous décidez d'annuler une édition complexe (modification de valeur, ajout d'entités associées, suppression d'autres entités associées, etc.). Mais l'entité est déjà modifiée dans un contexte partagé. Que vas-tu faire? Astuce: je ne connais aucune CancelChanges ou UndoChanges sur ObjectContext .

Je pense que nous n'avons pas à discuter de scénario de serveur. Le simple partage d'une seule entité entre plusieurs requêtes HTTP ou appels de services Web rend votre application inutile. Toute demande peut simplement déclencher SaveChanges et enregistrer des données partielles d’une autre demande, car vous partagez une seule unité de travail entre elles. Cela posera également un autre problème: le contexte et toute manipulation d’entités dans le contexte ou une connexion à une base de données utilisée par le contexte n’est pas thread-safe.

Même pour une application en lecture seule, un contexte global n'est pas un bon choix car vous souhaitez probablement obtenir de nouvelles données chaque fois que vous interrogez l'application.


Réponse populaire

Selon Daniel Simmons:

Créez une nouvelle instance ObjectContext dans une instruction Using pour chaque méthode de service afin qu'elle soit éliminée avant le retour de la méthode. Cette étape est essentielle pour l’évolutivité de votre service. Il s'assure que les connexions de base de données ne sont pas maintenues ouvertes lors d'appels de service et que l'état temporaire utilisé par une opération particulière est récupéré lors de la fin de l'opération. Entity Framework met automatiquement en cache les métadonnées et autres informations nécessaires dans le domaine d'application et les connexions aux bases de données des pools ADO.NET. Il est donc rapide de recréer le contexte à chaque fois.

Ceci est de son article complet ici:

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

Je crois que ce conseil s’applique aux requêtes HTTP et serait donc valable pour ASP.NET. Une application client lourd et dynamique telle qu'une application WPF peut constituer le seul cas pour un contexte "partagé".



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow