Які недоліки спочатку вимкнути ProxyCreationEnabled для CTP5 з коду EF


82

Єдиний спосіб, яким моя служба WCF може повернути класи з першої моделі коду, - це встановити значення ProxyCreationEnableза falseдопомогою коду нижче.

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

Які негативні наслідки від цього? Один виграш полягає в тому, що я можу принаймні отримати ці динамічні типи серіалізованими, щоб їх можна було надсилати по дроту за допомогою WCF.

Відповіді:


71

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

Якщо ви вимкнете ліниве завантаження, вам доведеться використовувати охоче завантаження для всіх властивостей навігації, які ви хочете використовувати (Включити на ObjectQuery). Відстеження змін не працює через WCF, воно працює лише для модифікації сутності, яка приєднана до ObjectContext.


7
Чи є вигода від продуктивності відключення ProxyCreationEnabled? Я часто захоплюю екземпляр DbContext просто для того, щоб, наприклад, зробити читання з нетерплячим завантаженням.
Кріс Москіні,

2
@ChrisMoschini "Коли об'єкт POCO не має проксі-сервера для відстеження змін, зміни знаходять шляхом порівняння вмісту ваших об'єктів із копією попереднього збереженого стану. Це глибоке порівняння стане тривалим процесом, коли у вашому контексті багато об'єктів , або коли ваші сутності мають дуже велику кількість властивостей, навіть якщо жодне з них не змінилося після останнього порівняння ". msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx
Ніклас Пітер

75

Якщо DbContext.Configuration.ProxyCreationEnabledвстановлено значення false, DbContext не буде завантажувати дочірні об'єкти для якогось батьківського об'єкта, якщо Includeметод не викликаний для батьківського об'єкта. Установка DbContext.Configuration.LazyLoadingEnabledна trueабо falseне матиме ніякого впливу на його поведінку.

Якщо DbContext.Configuration.ProxyCreationEnabledвстановлено значення true, дочірні об’єкти завантажуватимуться автоматично, а DbContext.Configuration.LazyLoadingEnabledзначення контролюватиме, коли завантажуватимуться дочірні об’єкти.


10

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

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

Цей клас у вашому EF.edmxтоді в yourmodel.Context.ttтодішньомуyourmodel.Context.cs


2
Це не відповідь, але мені все одно допомогло.
Акіра Ямамото

1
Чи маєте ви гарну пораду щодо автоматизації процесу введення цієї черги? Кожного разу, коли я відтворюватиму модель, я, безсумнівно, забуду встановити для властивості значення false, і це може зайняти години налагодження, перш ніж хтось зрозуміє, що з ним не так.
Конрад Вільтерстен

@konrad - Створіть код у частковому класі, щоб його не перевизначити. публічний частковий клас yourDataMoldelEntities ()
Mikee

@Mikee Справді? Я очікував би певних проблем через автогенерований конструктор, що зіткнувся з тим, який я написав у частковому класі ...
Конрад Вільтерстен

@konrad вони створили частковий клас 'type', щоб дати вам спосіб не перезаписувати ваш код
Mikee

6

(Використання Visual Studio 2013 або пізнішої версії)

Щоб уникнути редагування конструктора класу у вашій моделі EF кожного разу, коли ви оновлюєте модель з бази даних або іншим способом ініціюєте відновлення коду, правильне місце для зміни - у файлі коду T4, який відповідає за фактично створюючи код моделі. У мене була якась інша проблема з динамічними властивостями ще кілька років тому, коли я зрозумів основну механіку того, як насправді створювались класи та властивості. Т4 !!! Яке це диво: - Синтаксис T4 спочатку може бути дещо залякуючим, тому читати синтаксис мудро. Бути ДУЖЕ зосередженим під час внесення змін - також гарна ідея :-)

Так! Якщо ви подивитесь на свою модель, у вас є файл .tt під вашим файлом .edmx. Цей файл .tt (T4) - це скрипт, який фактично створює ваш клас моделі. Скрипт запускатиметься автоматично кожного разу, коли ви будуєте свою модель або вносите деякі зміни в редактор моделі.

Скажімо, ваш дескриптор моделі має ім’я Model1.edmx . У вас буде дерево під назвою Model1.Context.tt у дереві під ним. Ви також побачите файл Model1.Context.cs . Очевидно, що це фактичний файл коду для вашого контексту. Але цей файл є результатом запуску файлу скрипта .tt ! Він повністю динамічно створюється. Тож немає ідеї редагувати його.

Відкрийте файл .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, щоб побачити отриманий код. Якщо ви хочете змусити запустити скрипт шаблону, виберіть меню

Збірка - Трансформуйте всі шаблони T4

Неважко зрозуміти, чи помилились ви в коді T4, оскільки файл .cs або взагалі не буде зроблений, або з очевидними помилками, якщо ви відкриєте його в редакторі.


Ого - це справді має бути найкращим рішенням, оскільки воно вирішує проблему в корені. А також надає хорошу інформацію про взаємозв'язок файлу * .tt із отриманим файлом * .cs.
Дуглас Тіммс,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.