Каковы минусы отключения ProxyCreationEnabled для CTP5 кода EF

Единственный способ, с помощью которого моя служба WCF может возвращать классы из первой модели кода, устанавливается с помощью ProxyCreationEnable to false с помощью кода ниже.

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

Каковы негативные последствия этого? Одно из преимуществ заключается в том, что я могу, по крайней мере, преобразовать эти динамические типы, чтобы они могли быть отправлены по каналу с использованием WCF.

Ответ 1

Динамические прокси используются для отслеживания изменений и ленивой загрузки. Когда WCF пытается сериализовать объект, связанный контекст обычно закрывается и удаляется, но сериализация свойств навигации автоматически вызывает ложную загрузку (в закрытом контексте) = > исключение.

Если вы отключите ленивую загрузку, вам нужно будет использовать активную загрузку для всех свойств навигации, которые вы хотите использовать (Include on ObjectQuery). Изменения отслеживания не работают над WCF, он работает только для модификации объекта, который привязан к ObjectContext.

Ответ 2

Если для параметра DbContext.Configuration.ProxyCreationEnabled установлено значение false, DbContext не будет загружать дочерние объекты для какого-либо родительского объекта, если для родительского объекта не вызывается метод Include. Установка DbContext.Configuration.LazyLoadingEnabled в true или false не повлияет на его поведение.

Если для параметра DbContext.Configuration.ProxyCreationEnabled установлено значение true, дочерние объекты будут загружаться автоматически, а значение DbContext.Configuration.LazyLoadingEnabled будет контролироваться при загрузке дочерних объектов.

Ответ 3

Когда вы используете EF, он создает прокси по умолчанию для вашего класса. Решением может быть добавление этой строки в конструктор вашего класса DbContext. Ваша модель данных унаследована от класса DbContext, поэтому вы можете редактировать свою модель следующим образом:

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

Этот класс находится в вашем EF.edmx, затем в yourmodel.Context.tt, затем yourmodel.Context.cs

Ответ 4

(с использованием Visual Studio 2013 или более поздней версии)

Чтобы избежать редактирования конструктора класса в вашей модели EF каждый раз, когда вы обновляете модель из базы данных или каким-либо другим способом запускаете перестройку кода, правильное место для внесения изменений находится в файле кода T4, который отвечает за создание кода модели. У меня была еще одна проблема с динамическими свойствами несколько лет назад, когда я понял основную механику того, как были созданы классы и свойства. T4!!! Какое чудо это: -D Синтаксис T4 может сначала немного запугать, поэтому чтение синтаксиса является разумным. ОЧЕНЬ сфокусированный при внесении изменений также является хорошей идеей: -)

Итак! Если вы посмотрите в своей модели, у вас есть файл .tt под вашим .edmx файлом. Этот файл .tt(T4) - это script, который фактически создает класс модели. script будет запускаться автоматически каждый раз, когда вы создадите свою модель или внесите некоторые изменения в редактор модели.

Скажем, ваш дескриптор модели называется Model1.edmx. У вас будет файл с именем Model1.Context.tt в дереве под ним. Вы также увидите файл Model1.Context.cs. Это, очевидно, фактический файл кода для вашего контекста. Но этот файл результат запуска файла .tt script! Он полностью динамически создан. Так что не стоит его редактировать.

Откройте файл .tt, и вы увидите что-то вроде:

<#@ 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);
..
..

Еще около 50 строк вниз, код конструктора запускается сценарием.

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;
    <#
    }

Я добавил свойство base.Configuration.ProxyCreationEnabled = false;, чтобы он был самой первой строкой в ​​конструкторе.

Сохраните файл и откройте файл Model1.Context.cs, чтобы увидеть полученный код. Если вы хотите принудительно запустить шаблон script, выберите меню

Сборка - Tranform все шаблоны T4

Легко узнать, допустили ли вы ошибку в коде T4, поскольку файл .cs будет либо вообще не создан, либо с явными ошибками, если вы откроете его в редакторе.