2010-11-12 24 views
62

Me pregunto por qué no hay un método Detach en el objeto DbContext como lo hay para ObjectContext. Solo puedo asumir que esta omisión fue intencional, pero me cuesta entender por qué. Necesito poder separar y volver a unir entidades (por ejemplo, poner el caché en un proyecto ASP.NET). Sin embargo, como no puedo separar una entidad, cuando intento adjuntar una entidad asociada a un contexto anterior, aparece la excepción "Un objeto de entidad no puede ser referenciado por varias instancias de IEntityChangeTracker".Código Entity Framework Primero - Sin método Detach() en DbContext

¿Cuál es la guía aquí? ¿Me estoy perdiendo de algo?

+0

alguna de las personas cualquier cosa que decir: "¿Cuál es la guía aquí? ¿Me estoy perdiendo algo?" Personalmente, solo estoy interesado en utilizar Detach mientras busco una solución para leer una entidad desde el contexto, justo antes de guardar la instancia que vino desde atrás de la IU. Esto me da "Ya existe un objeto con la misma clave en ObjectStateManager.ObjectStateManager no puede rastrear varios objetos con la misma clave. " –

Respuesta

85

Para las personas que podrían tropezar con esta cuestión, como de CTP5 ahora tiene que escribir

((IObjectContextAdapter)context).ObjectContext 

con el fin de llegar a ObjectContext.

+1

+1 También tú necesita hacer referencia a System.Data.Entity – Pandincus

+0

+1 Limpio, elegante, un trazador de líneas. Me encanta. También quería decir que la interfaz se encuentra aquí específicamente: System.Data.Entity.Infrastructure.IObjectContextAdapter y sí, como señaló Pandincus. también debe hacer una referencia a System.Data.Entity. – dyslexicanaboko

38

DbContext utiliza un ObjectContext interna y equipo de EF hacen que este disponible como protegida propiedad en caso de que alguna vez tiene que bajar a la API de nivel inferior y suena como este es el caso aquí, para que pueda utilizar o exponer la funcionalidad requerida de un derivado DbContext:

public class YourContext : DbContext 
{ 
    public void Detach(object entity) 
    { 
     ObjectContext.Detach(entity);    
    } 
} 

a continuación, puede llamar a este método desde su controlador para separar una entidad.

Alternativamente, se puede cambiar incluso tener una API más rica:

public class YourContext : DbContext 
{ 
    public void ChangeObjectState(object entity, EntityState entityState) 
    { 
     ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState); 
    } 
} 

Aquí es cómo DbContext se parece a partir de los metadatos:

public class DbContext : IDisposable 
{  
    protected System.Data.Objects.ObjectContext ObjectContext { get; } 
    ... 
} 
+0

@Stacker esta no es la respuesta porque requiere el reparto descrito en la respuesta seleccionada anteriormente, es decir, el' DbContext' implementa 'IObjectContextAdapter' dándole la propiedad' ObjectContext' que es no accesible de otra manera. La combinación de las 2 respuestas da la respuesta de @ splite debajo de – eudaimos

+1

ChangeObjectState es bastante vago, está usando "algoritmo lineal con molde" que es ... Más o menos ... Sabes ... Reeeeally malo. –

15

EF: CF 4.1 RC1 y EF: CF 4.1 RTW tienen el mismo IObjectContextAdapter implementado de manera explícita:

public static class DbContextExtensions 
{ 
    public static void Detach(this System.Data.Entity.DbContext context, object entity) 
    { 
     ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity); 
    } 
} 

Microsoft decidió "Separar la tecnología es muy avanzada y debe ser ocultado". En mi humilde opinión, el hombre que inventó esto debe recibir un disparo, porque si agrega una nueva entidad, es difícil simplemente eliminarla sin realizar cambios en db (puede manipular con DbEntityEntry, pero esa es otra historia).

Editar 4 años más tarde:

Con EF6 (i alguna manera omiten EF5 :)) usted no necesita detach() más, lástima pues la eliminación de la entrada recién añadido no genera delete from [table] where [Id] = 0 como en EF4 - sólo puede llamar mySet.Remove(myFreshlyCreatedAndAddedEntity) y todo va a estar bien.

+0

shot? ¿quién necesita esa función de todos modos?: P – quetzalcoatl

+1

@quetzalcoatl: 'var context = ...; var poco = nuevo Poco(); context.Add (poco); context.Remove (poco); '<--- throws exception porque tienes que DETECTARLO, no eliminarlo - hey, detach está oculto ... –

+1

(5 minutos para editar desaparecido, sry :)) En ese momento yo estaba tan enojado ... Cuando estás haciendo la aplicación de Windows, tienes que tener alguna manera de "cancelar la creación de una entrada nueva, probablemente incompleta, pero mantener el contexto UoW" ... Nos deshacemos de toda la brecha de EF, y escribimos nuestro propio ORM: Hay no hay forma de utilizar la carga diferida (tengo un montón de Facturas y no puedo cargar cada Factura en la consulta individual "donde InvoiceId in (xxyy)" - Incluir no funciona en la forma que esperábamos) buscar antes de cada ejecución, wtf ...), crear proxies para más de 100 tipos poco toma demasiado tiempo y así sucesivamente ... –

6

lo general extender la clase base (se hereda de la DbContext) con la característica:

public class MyDbContext : DbContext 
{ 
    public ObjectContext ThisObjectContext 
    { 
     get 
     { 
      return ((IObjectContextAdapter)this).ObjectContext; 
     } 
    } 
} 

Más tarde se puede utilizar esta propiedad para la variedad de cosas útiles ... como Separar :)

Cuestiones relacionadas