¿Cuáles son las desventajas de desactivar ProxyCreationEnabled para CTP5 del código EF primero?

82

La única manera de que mi servicio WCF puede volver clases desde un primer modelo de código es mediante el establecimiento de la ProxyCreationEnablea falsecon el siguiente código.

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

¿Cuáles son las consecuencias negativas de hacer esto? Una ventaja es que al menos puedo serializar estos tipos dinámicos para que puedan enviarse por cable usando WCF.

Ralph Shillington
fuente

Respuestas:

71

Los proxies dinámicos se utilizan para el seguimiento de cambios y la carga diferida. Cuando WCF intenta serializar un objeto, el contexto relacionado generalmente se cierra y se elimina, pero la serialización de las propiedades de navegación activará automáticamente la carga diferida (en contexto cerrado) => excepción.

Si desactiva la carga diferida, deberá usar la carga ansiosa para todas las propiedades de navegación que desee usar (Incluir en ObjectQuery). El seguimiento de cambios no funciona en WCF, solo funciona para la modificación de la entidad que está adjunta a ObjectContext.

Ladislav Mrnka
fuente
7
¿Existe una ventaja de rendimiento al deshabilitar ProxyCreationEnabled? Con frecuencia tomo una instancia de DbContext solo para hacer una lectura con una carga ansiosa, por ejemplo.
Chris Moschini
2
@ChrisMoschini "Cuando una entidad POCO no tiene un proxy de seguimiento de cambios, los cambios se encuentran comparando el contenido de sus entidades con una copia de un estado guardado anterior. Esta comparación profunda se convertirá en un proceso largo cuando tenga muchas entidades en su contexto , o cuando sus entidades tienen una gran cantidad de propiedades, incluso si ninguna de ellas ha cambiado desde la última comparación ". msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx
Niklas Peter
75

Si DbContext.Configuration.ProxyCreationEnabledse establece en false, DbContext no cargará objetos secundarios para algún objeto principal a menos Includeque se llame al método en el objeto principal. Ajuste DbContext.Configuration.LazyLoadingEnableda true, o falseno tendrá ningún impacto en sus comportamientos.

Si DbContext.Configuration.ProxyCreationEnabledse establece en true, los objetos secundarios se cargarán automáticamente y el DbContext.Configuration.LazyLoadingEnabledvalor controlará cuándo se cargan los objetos secundarios.

Aleksey Timkov
fuente
10

Cuando usa EF, crea un proxy de forma predeterminada para su clase. Una solución puede ser agregar esta línea en el constructor de su clase DbContext. Su modelo de datos heredado de la clase DbContext, por lo que puede editar su modelo de esta manera:

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

Esta clase está en tu EF.edmxentonces en el yourmodel.Context.ttentoncesyourmodel.Context.cs

Vicente Zambrano
fuente
2
Esta no es una respuesta, pero me ayudó de todos modos.
Akira Yamamoto
1
¿Tiene una buena sugerencia sobre cómo automatizar el proceso de puesta en esa línea? Cada vez que recrearé un modelo, seguramente me olvidaré de establecer la propiedad en falso y eso puede llevar horas de depuración antes de que alguien se dé cuenta de lo que está mal.
Konrad Viltersten
@konrad: crea el código en una clase parcial para que no se anule. clase pública parcial yourDataMoldelEntities ()
Mikee
@Mikee ¿De verdad? Esperaría algún tipo de problemas debido a que el constructor generado automáticamente colisiona con el escrito por mí en la clase parcial ...
Konrad Viltersten
@konrad crearon el 'tipo' de clase parcial para darle una manera de no sobrescribir su código
Mikee
6

(Con Visual Studio 2013 o posterior)

Para evitar la edición del constructor de la clase en su modelo EF cada vez que actualiza el modelo de la base de datos, o de alguna otra manera desencadena la reconstrucción del código, el lugar adecuado para realizar el cambio es en el archivo de código T4 que es responsable de creando realmente el código del modelo. Tuve algún otro problema con las propiedades dinámicas hace unos años cuando entendí la mecánica subyacente de cómo se crearon realmente las clases y propiedades. T4 !!! Qué milagro es :- La sintaxis de D T4 puede ser un poco intimidante al principio, así que leer sobre la sintaxis es prudente. Estar MUY concentrado al hacer cambios también es una buena idea :-)

¡Entonces! Si busca en su modelo, tiene un archivo .tt debajo de su archivo .edmx. Este archivo .tt (T4) es el script que realmente crea su clase de modelo. La secuencia de comandos se ejecutará automáticamente cada vez que cree su modelo o realice algunos cambios en el editor de modelos.

Digamos que su descriptor de modelo se llama Model1.edmx . Tendrá un archivo llamado Model1.Context.tt en el árbol debajo de él. También verá un archivo Model1.Context.cs . Obviamente, este es el archivo de código real para su contexto. ¡Pero este archivo es el resultado de la ejecución del archivo de script .tt ! Se crea de forma completamente dinámica. Así que no tengo idea de editarlo.

Abra el archivo .tt y verá algo como:

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

Otras 50 líneas más abajo, el código del constructor se está escribiendo.

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

He agregado la propiedad base.Configuration.ProxyCreationEnabled = false;para que sea la primera línea del constructor.

Guarde su archivo y abra el archivo Model1.Context.cs para ver el código resultante. Si desea forzar la ejecución del script de plantilla, seleccione el menú

Construir - Transformar todas las plantillas T4

Es fácil saber si ha cometido un error en su código T4, ya que el archivo .cs no se creará en absoluto o tendrá errores obvios si lo abre en el editor.

Per Malmstedt
fuente
Vaya, esta debería ser la solución preferida, ya que soluciona el problema desde la raíz. Y también proporciona una buena base sobre la relación del archivo * .tt con el archivo * .cs resultante.
Douglas Timms