La seule façon dont mon service WCF peut renvoyer des classes à partir d'un premier modèle de code consiste à définir ProxyCreationEnable
sur false
à l'aide du code ci-dessous.
((IObjectContextAdapter)MyDb).ObjectContext.ContextOptions.ProxyCreationEnable = false;
Quelles sont les conséquences négatives de cela? Un gain est que je peux au moins obtenir ces types dynamiques sérialisés afin qu'ils puissent être envoyés sur le câble en utilisant WCF.
Les proxys dynamiques sont utilisés pour le suivi des modifications et le chargement paresseux. Lorsque WCF essaie de sérialiser l'objet, le contexte associé est généralement fermé et supprimé, mais la sérialisation des propriétés de navigation déclenche automatiquement le chargement différé (dans un contexte fermé) => exception.
Si vous désactivez le chargement paresseux, vous devrez utiliser un chargement rapide pour toutes les propriétés de navigation que vous souhaitez utiliser (Inclure sur ObjectQuery). Le suivi des modifications ne fonctionne pas sur WCF, il fonctionne uniquement pour la modification de l'entité qui est attachée à ObjectContext.
Si DbContext.Configuration.ProxyCreationEnabled
est défini sur false
, DbContext ne charge pas les objets enfants pour un objet parent, sauf si la méthode Include
est appelée sur l'objet parent. Réglage DbContext.Configuration.LazyLoadingEnabled
à true
ou false
n'aura aucun impact sur ses comportements.
Si DbContext.Configuration.ProxyCreationEnabled
est défini sur true
, les objets enfants seront chargés automatiquement et DbContext.Configuration.LazyLoadingEnabled
value contrôlera le chargement des objets enfants.
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érité 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
(Utilisation de Visual Studio 2013 ou version ultérieure)
Pour éviter la modification du constructeur de classe dans votre modèle EF à chaque fois que vous actualisez le modèle à partir de la base de données, ou d'une autre manière, déclenchez la reconstruction du code, l'emplacement approprié pour effectuer la modification se trouve dans le fichier de code T4 qui est responsable de créer réellement le code du modèle. J'ai eu un autre problème avec les propriétés dynamiques il y a quelques années lorsque j'ai compris la mécanique sous-jacente de la façon dont les classes et les propriétés étaient réellement créées. T4 !!! Quel miracle c'est: - La syntaxe D T4 peut être un peu intimidante au début, il est donc sage de lire la syntaxe. Être TRÈS concentré lors des changements est également une bonne idée :-)
Alors! 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 apportez des modifications dans l'éditeur de modèle.
Supposons que votre descripteur de modèle soit nommé Model1.edmx. Vous aurez un fichier nommé Model1.Context.tt dans l'arborescence en dessous. Vous verrez également un fichier Model1.Context.cs. 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 de script .tt! Il est entièrement créé dynamiquement. Donc aucune idée de le modifier.
Ouvrez le fichier .tt et vous verrez quelque chose comme:
<#@ 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 cinquantaine de lignes plus loin, le code constructeur est en cours de 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;
pour que ce 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 souhaitez forcer l'exécution du script de modèle, 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 créé du tout, ou avec des erreurs évidentes si vous l'ouvrez dans l'éditeur.