¿Por qué mi entidad Código Marco primer nulo colección proxy y por qué no puedo configurarlo?

StackOverflow https://stackoverflow.com/questions/4069563

Pregunta

Estoy utilizando DBContext y tengo dos clases cuyas propiedades son todos virtual. Puedo ver en el depurador que estoy recibiendo un objeto proxy cuando consulto el contexto. Sin embargo, una propiedad de colección sigue siendo nula cuando intento agregar a ella. Pensé que el proxy se aseguraría de que la colección se ha inicializado.

Debido a que mi objeto Poco se puede utilizar fuera de su contexto de datos, he añadido un cheque por la colección siendo nula en el constructor y crearlo si es necesario:

public class DanceStyle
{
    public DanceStyle()
    {
        if (DanceEvents == null)
        {
            DanceEvents = new Collection<DanceEvent>();
        }
    }
    ...
    public virtual ICollection<DanceEvent> DanceEvents { get; set; }
}

que funciona fuera del contexto de datos pero si puedo recuperar un objeto mediante una consulta, aunque la prueba es verdadera, cuando intento configurarlo, consigo siguiente excepción: 'La propiedad 'DanceEvents' de tipo 'DanceStyle_B6089AE40D178593955F1328A70EAA3D8F0F01DDE9F9FBD615F60A34F9178B94' no puede ser set porque la colección ya está establecido en un EntityCollection. "

puedo ver es nula y no se puede añadir a la misma, pero tampoco se puede establecer que a una colección, porque el proxy dice que ya está establecido. Por lo tanto no puedo usarlo. Estoy confundido.

Esta es la clase DanceEvent:

public class DanceEvent
{
    public DanceEvent()
    {
        if (DanceStyles == null)
        {
            DanceStyles = new Collection<DanceStyle>();
        }
    }
    ...
    public virtual ICollection<DanceStyle> DanceStyles { get; set; }
}

he omitido las otras propiedades de tipo valor del código de seguridad. No tengo otras asignaciones para aquellas clases en la clase de contexto.

¿Fue útil?

Solución 2

He encontrado la solución a este problema aquí: Código Primera adición a las colecciones? Cómo utilizar código Primero con repositorios?

I eliminó 'virtual' de todas las propiedades excepto colecciones y objetos cargados perezosas, es decir, todos los tipos nativos.

Pero todavía no entiendo cómo se puede terminar con la situación en la que usted tiene una colección nula de que no se puede utilizar y no tienen manera de ponerlo en una colección válida.

esta respuesta de Rowan Miller en un foro de MSDN

  

Hola,

     

Si realiza todas sus propiedades virtuales a continuación, EF generará clases de proxy en tiempo de ejecución que se deriva de su POCO clasifican, estos servidores proxy permiten EF para averiguar acerca de los cambios en tiempo real en lugar de tener que capturar los valores originales de su objeto y luego buscar cambios al guardar (esto es, obviamente, tiene ventajas de rendimiento y uso de memoria, pero la diferencia será insignificante a menos que tenga un gran número de entidades cargados en la memoria). Estos son conocidos como 'proxies' El seguimiento de cambios, si usted hace sus propiedades de navegación virtuales a continuación, se sigue generando un proxy, pero es mucho más simple y solo incluye algo de lógica para llevar a cabo la carga diferida cuando accede a una propiedad de navegación.

     

Debido a que su código original estaba generando proxies seguimiento de cambios, EF estaba reemplazando a su propiedad de colección con un tipo especial de recogida para ayudar a encontrar a cabo acerca de los cambios. Debido a que tratar de ajustar la parte posterior recogida a una simple lista en el constructor que está recibiendo la excepción.

     

A menos que usted está viendo los problemas de rendimiento Me gustaría seguir la sugerencia de Terrence y simplemente eliminar 'virtual' de sus propiedades no navegación.

     

~ Rowan

Por lo tanto, parece que sólo tengo el problema con un 'proxy de seguimiento de cambios' completo si todas mis propiedades son virtuales. Pero teniendo en cuenta que, ¿por qué puedo yo todavía no utilice la propiedad virtual en el proxy de seguimiento de cambios? Este código hace saltar en la línea tres, porque ds2.DanceEvents es nula y no se pueden establecer en el constructor:

DanceStyle ds2 = ctx.DanceStyles.Where(ds => ds.DanceStyleId == 1).Single();
DanceEvent evt = CreateDanceEvent();
ds2.DanceEvents.Add(evt);

Todavía estoy confundido, a pesar de que mi código está trabajando ahora debido a la revisión anterior.

Otros consejos

A medida que observó correctamente en la respuesta a su propia pregunta, la eliminación de la palabra "virtual" de las propiedades de la colección de obras de todo el problema, al impedir que el marco de la entidad a partir de la creación de un proxy de seguimiento de cambios. Sin embargo, esto no es una solución para muchas personas, ya que los proxies de seguimiento de cambios pueden ser muy convenientes y pueden ayudar a prevenir problemas cuando se olvida de detectar cambios en los lugares adecuados en el código.

Un mejor enfoque sería modificar sus clases POCO, de modo que ejemplifican las propiedades de la colección en su acceso get, en lugar de en el constructor. Aquí está tu clase POCO, modificado para permitir el seguimiento de cambios creación de proxy:

public class DanceEvent
{
    private ICollection<DanceStyle> _danceStyles;
    public virtual ICollection<DanceStyle> DanceStyles
    {
        get { return _danceStyles ?? (_danceStyles = new Collection<DanceStyle>()); }
        protected set { _danceStyles = value; }
    }
}

En el código anterior la propiedad de colección ya no es automática, sino que tiene un campo de respaldo. Es mejor si se deja el colocador protegida, evitando cualquier código (que no sea el proxy) de modificar posteriormente estas propiedades. Usted notará que el constructor ya no era necesario y se separó.

pregunta antiguo ...

Poco clase:

public partial class MyPOCO
{
    public MyPOCO()
    {
        this.MyPocoSub = new HashSet<MyPocoSub>();
    }

    //VIRTUAL
    public virtual ICollection<MyPocoSub> MyPocoSub { get; set; }
}

y el código de proxy:

    public override ICollection<MyPocoSubSet> MyPocoSubSets
    {
        get
        {
            ICollection<MyPocoSubSet> myPocoSubSets = base.MyPocoSubSets;
            if (!this.ef_proxy_interceptorForMyPocoSubSets(this, myPocoSubSets))
            {
                return base.MyPocoSubSets;
            }
            return myPocoSubSets;
        }
        set
        {
            if (value != this.RelationshipManager.GetRelatedEnd("WindowsFormsApplication.Models.MyPocoSubSet_MyPOCO", "MyPocoSubSet_MyPOCO_Source"))
            {
                // EXCEPTION 
                throw new InvalidOperationException("The property 'MyPocoSubSets' on type 'MyPOCO_A78FCE6C6A890855C68B368B750864E3136B589F9023C7B1D90BF7C83FD291AC' cannot be set because the collection is already set to an EntityCollection.");
            }
            base.MyPocoSubSets = value;
        }
    }

Como se puede ver que la excepción se crió en la clase proxy en ExtityFramework 5. Esto significa que todavía existen comportamiento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top