Recibo el siguiente error al intentar adjuntar un objeto que ya está adjunto a un contexto dado a través de context.AttachTo(...)
:
Ya existe un objeto con la misma clave en ObjectStateManager. ObjectStateManager no puede rastrear varios objetos con la misma clave.
¿Hay alguna forma de lograr algo en la línea de:
context.IsAttachedTo(...)
¡Salud!
Editar:
El método de extensión que describió Jason está cerca, pero no funciona para mi situación.
Estoy tratando de trabajar un poco usando el método descrito en la respuesta a otra pregunta:
Mi código se parece un poco a esto:
var user = new User() { Id = 1 };
context.AttachTo("Users", user);
comment.User = user;
context.SaveChanges();
Esto funciona bien, excepto cuando hago algo más para ese usuario donde uso el mismo método e intento adjuntar un User
objeto ficticio . Esto falla porque he adjuntado previamente ese objeto de usuario ficticio. ¿Cómo puedo verificar esto?
fuente
(T)entry.Entity
veces devuelve nulo?T
ya lo estáIEntityWithKey
, ¿no puede simplemente usar suentity.EntityKey
propiedad en lugar de reconstruirlo o necesita adivinar / proporcionar elEntitySetName
?Un enfoque más simple es:
bool isDetached = context.Entry(user).State == EntityState.Detached; if (isDetached) context.Users.Attach(user);
fuente
.Include()
'las propiedades de navegación ed también se intentaron unir cuando se llama.Attach
o establece elEntityState
aEntityState.Unchanged
- y van a entrar en conflicto si alguna de las entidades se refieren a la misma entidad. No he descubierto cómo adjuntar solo la entidad base, por lo que tuve que rediseñar un poco el proyecto, para usar contextos separados para cada "transacción comercial", como fue diseñado. Tomaré nota de esto para proyectos futuros.Pruebe este método de extensión (esto no ha sido probado y es improvisado):
public static bool IsAttachedTo(this ObjectContext context, object entity) { if(entity == null) { throw new ArgumentNullException("entity"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) { return (entry.State != EntityState.Detached); } return false; }
Dada la situación que describe en su edición, es posible que deba usar la siguiente sobrecarga que acepta
EntityKey
un objeto en lugar de un:public static bool IsAttachedTo(this ObjectContext, EntityKey key) { if(key == null) { throw new ArgumentNullException("key"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(key, out entry)) { return (entry.State != EntityState.Detached); } return false; }
Para construir un
EntityKey
en su situación, use lo siguiente como guía:EntityKey key = new EntityKey("MyEntities.User", "Id", 1);
Puede obtener el
EntityKey
de una instancia existente deUser
utilizando la propiedadUser.EntityKey
(desde la interfazIEntityWithKey
).fuente
TryGetObjectStateEntry
que acepta un enEntityKey
lugar de unobject
. He editado en consecuencia. Avísame si esto no ayuda y volveremos a la mesa de dibujo.Usando la clave de entidad del objeto que está intentando verificar:
var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey"); if (entry.State == EntityState.Detached) { // Do Something }
Amabilidad,
Dan
fuente
Esto no responde directamente a la pregunta de OP, pero así es como resolví la mía.
Esto es para aquellos que están usando en
DbContext
lugar deObjectContext
.public TEntity Retrieve(object primaryKey) { return DbSet.Find(primaryKey); }
Método DbSet.Find :
Básicamente, devuelve el objeto adjunto del dado,
primaryKey
por lo que solo necesita aplicar los cambios en el objeto devuelto para mantener la instancia correcta.fuente