Jakie są wady wyłączenia ProxyCreationEnabled dla CTP5 kodu EF w pierwszej kolejności

82

Jedyny sposób, że moja usługa WCF może powrócić zajęcia z kodem pierwszego modelu jest ustawienie ProxyCreationEnabledo falsestosując poniższy kod.

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

Jakie są negatywne konsekwencje takiego postępowania? Jedną z korzyści jest to, że mogę przynajmniej uzyskać serializację tych typów dynamicznych, aby można je było przesyłać za pośrednictwem sieci kablowej za pomocą WCF.

Ralph Shillington
źródło

Odpowiedzi:

71

Dynamiczne serwery proxy służą do śledzenia zmian i leniwego ładowania. Gdy usługa WCF próbuje serializować obiekt, powiązany kontekst jest zwykle zamykany i usuwany, ale serializacja właściwości nawigacji automatycznie wyzwala ładowanie z opóźnieniem (w zamkniętym kontekście) => wyjątek.

Jeśli wyłączysz leniwe ładowanie, będziesz musiał użyć przyspieszonego ładowania dla wszystkich właściwości nawigacji, których chcesz użyć (Uwzględnij w ObjectQuery). Śledzenie zmian nie działa w programie WCF, działa tylko w przypadku modyfikacji jednostki, która jest dołączona do ObjectContext.

Ladislav Mrnka
źródło
7
Czy wyłączenie ProxyCreationEnabled ma wpływ na wydajność? Na przykład często pobieram wystąpienie DbContext tylko po to, aby wykonać odczyt z zachłannym ładowaniem.
Chris Moschini
2
@ChrisMoschini "Gdy encja POCO nie ma serwera proxy do śledzenia zmian, zmiany można znaleźć, porównując zawartość twoich encji z kopią poprzedniego zapisanego stanu. To głębokie porównanie stanie się procesem długotrwałym, gdy w kontekście masz wiele jednostek lub gdy twoje byty mają bardzo dużą liczbę właściwości, nawet jeśli żadna z nich nie zmieniła się od czasu ostatniego porównania. " msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx
Niklas Peter
75

Jeśli DbContext.Configuration.ProxyCreationEnabledjest ustawiona na false, DbContext nie załaduje obiektów podrzędnych dla niektórych obiektów nadrzędnych, chyba że Includemetoda zostanie wywołana na obiekcie nadrzędnym. Ustawianie DbContext.Configuration.LazyLoadingEnabledsię truelub falsenie będzie miało wpływu na jego zachowanie.

Jeśli DbContext.Configuration.ProxyCreationEnabledjest ustawiona na true, obiekty podrzędne będą ładowane automatycznie, a DbContext.Configuration.LazyLoadingEnabledwartość będzie sterować ładowaniem obiektów podrzędnych.

Aleksey Timkov
źródło
10

Gdy używasz EF, domyślnie tworzy serwer proxy dla Twojej klasy. Rozwiązaniem może być dodanie tego wiersza w konstruktorze klasy DbContext. Twój model danych odziedziczony z klasy DbContext, więc możesz edytować model w następujący sposób:

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

Ta klasa jest w twoim EF.edmxwtedy w yourmodel.Context.ttwtedyyourmodel.Context.cs

Vicente Zambrano
źródło
2
To nie jest odpowiedź, ale i tak mi pomogła.
Akira Yamamoto
1
Czy masz dobrą sugestię, jak zautomatyzować proces ustawiania tej linii? Za każdym razem, gdy odtwarzam model, na pewno zapomnę o ustawieniu właściwości na fałsz, a debugowanie może zająć godziny, zanim ktoś zorientuje się, co jest z nim nie tak.
Konrad Viltersten
@konrad - Utwórz kod w częściowej klasie, aby nie został nadpisany. public częściowa klasa yourDataMoldelEntities ()
Mikee
@Mikee Naprawdę? Spodziewałbym się jakichś problemów z powodu kolizji konstruktora generowanego automatycznie z konstruktorem napisanym przeze mnie w klasie częściowej ...
Konrad Viltersten
@konrad stworzyli częściowy `` typ '' klasy, aby dać ci sposób, aby nie nadpisywać kodu
Mikee
6

(Korzystanie z programu Visual Studio 2013 lub nowszego)

Aby uniknąć edycji konstruktora klasy w modelu EF za każdym razem, gdy odświeżasz model z bazy danych lub w inny sposób wyzwalasz przebudowę kodu, właściwym miejscem do wprowadzenia zmiany jest plik kodu T4, który jest odpowiedzialny za faktycznie tworząc kod modelu. Miałem inny problem z właściwościami dynamicznymi kilka lat temu, kiedy zrozumiałem podstawową mechanikę tworzenia klas i właściwości. T4 !!! Cóż to za cud :-D Składnia T4 może na początku nieco onieśmielać, więc czytanie składni jest mądre. Bycie BARDZO skupionym na wprowadzaniu zmian jest również dobrym pomysłem :-)

Więc! Jeśli zajrzysz do swojego modelu, masz plik .tt pod plikiem .edmx. Ten plik .tt (T4) jest skryptem, który faktycznie tworzy klasę modelu. Skrypt będzie uruchamiany automatycznie za każdym razem, gdy będziesz budować model lub wprowadzać zmiany w edytorze modelu.

Powiedzmy, że twój deskryptor modelu nosi nazwę Model1.edmx . Będziesz mieć plik o nazwie Model1.Context.tt w drzewie pod nim. Zobaczysz również plik Model1.Context.cs . Jest to oczywiście rzeczywisty plik kodu dla twojego kontekstu. Ale ten plik jest wynikiem działania skryptu .tt ! Jest tworzony całkowicie dynamicznie. Więc nie ma pomysłu, żeby go edytować.

Otwórz plik .tt, a zobaczysz coś takiego:

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

Kolejne 50 linii w dół, kod konstruktora jest w trakcie tworzenia skryptów.

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

Dodałem tę właściwość base.Configuration.ProxyCreationEnabled = false;, aby była to pierwsza linia w konstruktorze.

Zapisz plik i otwórz plik Model1.Context.cs, aby wyświetlić wynikowy kod. Jeśli chcesz wymusić uruchomienie skryptu szablonu, wybierz menu

Buduj - przekształcaj wszystkie szablony T4

Łatwo jest wiedzieć, czy popełniłeś błąd w swoim kodzie T4, ponieważ plik .cs albo w ogóle nie zostanie utworzony, albo z oczywistymi błędami, jeśli otworzysz go w edytorze.

Per Malmstedt
źródło
Wow - to naprawdę powinno być preferowanym rozwiązaniem, ponieważ rozwiązuje problem w katalogu głównym. Zapewnia również dobre tło dotyczące relacji pliku * .tt z wynikowym plikiem * .cs.
Douglas Timms