81 votes

Quels sont les inconvénients de désactiver ProxyCreationEnabled pour la CTP5 du code EF d'abord

La seule façon pour mon service WCF de renvoyer des classes à partir d'un modèle de type "code first" est de définir l'attribut "code first". ProxyCreationEnable à false en utilisant le code ci-dessous.

((IObjectContextAdapter)MyDb).ObjectContext.ContextOptions.ProxyCreationEnable = false;

Quelles sont les conséquences négatives d'une telle démarche ? Un gain est que je peux au moins obtenir ces types dynamiques sérialisés afin qu'ils puissent être envoyés sur le fil en utilisant WCF.

71voto

Aleksey Timkov Points 161

Si DbContext.Configuration.ProxyCreationEnabled est réglé sur false Dans le cas d'un objet parent, DbContext ne chargera pas les objets enfants à moins que Include est appelée sur l'objet parent. Réglage de DbContext.Configuration.LazyLoadingEnabled à true o false n'aura aucun impact sur ses comportements.

Si DbContext.Configuration.ProxyCreationEnabled est réglé sur true les objets enfants seront chargés automatiquement, et DbContext.Configuration.LazyLoadingEnabled permettra de contrôler le moment où les objets enfants sont chargés.

70voto

Ladislav Mrnka Points 218632

Les proxies dynamiques sont utilisés pour le suivi des modifications et le chargement paresseux. Quand WCF essaie de sérialiser l'objet, le contexte lié est habituellement fermé et disposé mais la sérialisation des propriétés de navigation déclenchera automatiquement le chargement paresseux (sur le contexte fermé) => exception.

Si vous désactivez le chargement paresseux, vous devrez utiliser le chargement rapide pour toutes les propriétés de navigation que vous souhaitez utiliser (Include on ObjectQuery). Le suivi des changements ne fonctionne pas sur WCF, il fonctionne seulement pour la modification de l'entité qui est attachée à ObjectContext.

10voto

Lorsque vous utilisez EF, il crée un proxy par défaut pour votre classe. Une solution peut être d'ajouter cette ligne dans le constructeur de votre classe DbContext. Votre modèle de données hérite de la classe DbContext, vous pouvez donc modifier votre modèle comme ceci :

    public yourDataModelEntities()
        : base("name=yourDataModelEntities")
    {
        base.Configuration.ProxyCreationEnabled = false;
    }

Cette classe est dans votre EF.edmx puis dans le yourmodel.Context.tt puis yourmodel.Context.cs

6voto

Per Malmstedt Points 301

(Utilisation de Visual Studio 2013 ou plus)

Pour éviter de modifier le constructeur de classe de votre modèle EF à chaque fois que vous rafraîchissez le modèle à partir de la base de données, ou que vous déclenchez d'une autre manière la reconstruction du code, l'endroit approprié pour effectuer le changement est le fichier de code T4 qui est responsable de la création effective du code du modèle. J'ai eu d'autres problèmes avec les propriétés dynamiques il y a quelques années, lorsque j'ai compris les mécanismes sous-jacents de la création des classes et des propriétés. T4 !!! C'est un miracle :-D La syntaxe T4 peut être un peu intimidante au début, il est donc judicieux de se documenter sur la syntaxe. Il est également conseillé d'être TRÈS concentré lorsque vous effectuez des modifications :-)

Donc, si vous regardez dans votre modèle, vous avez un fichier .tt sous votre fichier .edmx. Ce fichier .tt (T4) est le script qui crée réellement votre classe de modèle. Le script sera exécuté automatiquement chaque fois que vous construisez votre modèle ou que vous apportez des modifications dans l'éditeur de modèle.

Disons que votre descripteur de modèle s'appelle Modèle1.edmx . Vous aurez un fichier nommé Modèle1.Contexte.tt dans l'arbre en dessous. Vous verrez également un Modèle1.Contexte.cs fichier. Il s'agit évidemment du fichier de code réel pour votre contexte. Mais ce fichier est le résultat de l'exécution du fichier .tt script. ! Il est entièrement créé de manière dynamique. Donc pas question de le modifier.

Ouvrez le fichier .tt et vous verrez quelque chose comme ça :

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF6.Utility.CS.ttinclude"#><#@
 output extension=".cs"#><#

const string inputFile = @"Model1.edmx";
var textTransform = DynamicTextTransformation.Create(this);
..
..

Une autre cinquantaine de lignes plus bas, le code du constructeur est scripté.

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
<#
if (container.FunctionImports.Any())
{
#>
using System.Data.Entity.Core.Objects;
using System.Linq;
<#
}
#>

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
    {
        public <#=code.Escape(container)#>()
            : base("name=<#=container.Name#>")
        {
        base.Configuration.ProxyCreationEnabled = false;
    <#
    if (!loader.IsLazyLoadingEnabled(container))
    {
    #>
            this.Configuration.LazyLoadingEnabled = false;
    <#
    }

J'ai ajouté la propriété base.Configuration.ProxyCreationEnabled = false; afin qu'elle soit la toute première ligne du constructeur.

Enregistrez votre fichier, et ouvrez le fichier Model1.Context.cs pour voir le code résultant. Si vous voulez forcer l'exécution du modèle script, sélectionnez le menu

Build - Transformez tous les modèles T4

Il est facile de savoir si vous avez fait une erreur dans votre code T4, car le fichier .cs ne sera pas du tout fait ou contiendra des erreurs évidentes si vous l'ouvrez dans l'éditeur.

-5voto

ideafountain Points 310

Si je désactive ProxyCreationEnabled (à false), mes tests unitaires ne fonctionnent pas. Je ne sais pas s'il existe des solutions de contournement... Mais c'est l'un des problèmes que j'ai rencontrés.

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