2012-09-07 16 views
16

Estoy trabajando en un sistema usando Entityframework y he pasado más de 12 meses, y el proyecto ha ido bien, hasta ayer, donde ahora recibí un extraño error que no tengo ni idea de por qué ocurre estoy haciendo nada diferente a lo que he hecho antes, pero una vez me carga la entidad en cuestión y tratar de acceder a cualquier entidad niño me sale el siguiente error:EntityFramework - Error de proxy de la entidad

The entity wrapper stored in the proxy does not reference the same proxy 

¿Alguien puede arrojar alguna luz sobre lo que en realidad esto significa y qué podría causar esto?

Mostrar mi código realmente no ayuda.

Aquí es una versión simplificada del código:

var quote = new QuoteHelper().GetById(orderId); 
var updatedQuotes = new Provider().GetExportQuotes(quote.DeparturePoint.Id,quote.DestinationPoint); 

El error se produce cuando se accede correctamente DeparturePoint y DestinationPoint pero cargas cita, y todas las propiedades están cargados.

La entidad Cita se ve un poco como esto:

public class Quote : BaseQuote, ICloneable 
{ 
    public Guid DeparturePointId { get; set; } 
    public virtual LocationPoint DeparturePoint{ get; set; } 

    public Guid DestinationPointId { get; set; } 
    public virtual LocationPoint DestinationPoint{ get; set; } 
} 

Respuesta

32

Esto sucedió a mí también cuando traté de poner en práctica ICloneable en mi entidad y clonado utilizando MemberwiseClone. Funcionó muy bien cuando estaba usando entidades que me instalé. Sin embargo, cuando utilicé esto para clonar una entidad que se había cargado usando EF, obtuve este error cada vez que intenté agregarlo a un DbSet (o en varias otras partes).

Después de algunas excavaciones, descubrí que al clonar una entidad cargada con EF, está clonando también la clase proxy. Una de las cosas que una clase proxy lleva consigo es una referencia al envoltorio de la entidad dada. Debido a que una copia superficial solo copia una referencia al contenedor, de repente tiene dos entidades que tienen la misma instancia de contenedor.

En este punto, EF cree que ha creado o tomado prestada una clase de proxy diferente para su entidad que asume es para propósitos maliciosos y lo bloquea.

Editar

He aquí un fragmento que he creado para evitar este problema. Tenga en cuenta que esto hará un buen trabajo al copiar solo las propiedades de EF, pero no es perfecto. Tenga en cuenta que deberá modificarlo si tiene campos privados que también se deben copiar, pero se entiende la idea.

/// <summary> 
    /// Makes a shallow copy of an entity object. This works much like a MemberwiseClone 
    /// but directly instantiates a new object and copies only properties that work with 
    /// EF and don't have the NotMappedAttribute. 
    /// </summary> 
    /// <typeparam name="TEntity">The entity type.</typeparam> 
    /// <param name="source">The source entity.</param> 
    public static TEntity ShallowCopyEntity<TEntity>(TEntity source) where TEntity : class, new() 
    { 

     // Get properties from EF that are read/write and not marked witht he NotMappedAttribute 
     var sourceProperties = typeof(TEntity) 
           .GetProperties() 
           .Where(p => p.CanRead && p.CanWrite && 
              p.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.NotMappedAttribute), true).Length == 0); 
     var newObj = new TEntity(); 

     foreach (var property in sourceProperties) 
     { 

      // Copy value 
      property.SetValue(newObj, property.GetValue(source, null), null); 

     } 

     return newObj; 

    } 
+1

Gracias, tuve un método de clonación horrible y me pareció que parecía que la magia que necesitaba parece que no lo es. Gracias. – JamesStuddart

+0

MemberwiseClone a menudo es la magia que necesitas, pero EF hace algunas cosas únicas. Por cierto, si encuentra que esta solución no es suficiente, también he oído de personas que usan [AutoMapper] (http://automapper.org/) para un mecanismo de clonación barato. No fue pensado para esto, pero eso no significa que no sea una solución perfectamente buena. –

+0

Gracias, he solucionado un problema por el problema, pero cuando tenga tiempo para volver a implementarlo, implementaré una de las soluciones que usted ha dado.Gracias por su visión, parece que no hay mucho por ahí sobre este tema y espero que esto ayude a otras personas también. – JamesStuddart

1

encima solución puede producirse como error "cambios conflictivos en el papel x de la relación y se han detectado". Logro ese error al usar este método;

public virtual TEntity DetachEntity(TEntity entityToDetach) 
    { 
     if (entityToDetach != null) 
      context.Entry(entityToDetach).State = EntityState.Detached; 
     context.SaveChanges(); 
     return entityToDetach; 
    } 

espero que funcione para usted también.

Cuestiones relacionadas