No se pudo adjuntar una entidad de tipo porque otra entidad del mismo tipo ya tiene el mismo valor de clave principal

Mensaje de error: la conexión de una entidad de tipo falló porque otra entidad del mismo tipo ya tiene el mismo valor de clave principal.

Pregunta: ¿Cómo adjunto una entidad de una manera similar a la demostrada en el método AttachActivity en el código a continuación?

Tengo que asumir que la parte de “otra entidad” del mensaje de error anterior se refiere a un objeto que existe en la memoria pero está fuera del scope (??). Observo esto porque la propiedad Local del DBSet para el tipo de entidad que estoy tratando de adjuntar devuelve cero.

Estoy razonablemente seguro de que las entidades no existen en el contexto porque paso por el código y observo el contexto a medida que se crea. Las entidades se agregan en las pocas líneas inmediatamente después de la creación del dbcontext.

Estoy probando las entidades adjuntas como se especifica aquí: ¿cuál es la forma más razonable de averiguar si la entidad está vinculada a dbContext o no?

Al mirar a los locales en la ventana de locals de visual studio, no veo ninguna entidad de tipo Actividad (independientemente de la ID) excepto la que estoy tratando de adjuntar.

El código se ejecuta en este orden: Intente -> ModificarProyecto -> Adjuntar actividad

El código falla en la AttachActivity en la línea comentada.

Tenga en cuenta el código entre los comentarios de depuración que se lanzarán si alguna entidad se ha agregado al contexto.

private string AttachActivity(Activity activity) { string errorMsg = ValidateActivity(activity); // has no code yet. No. It does not query db. if(String.IsNullOrEmpty(errorMsg)) { // debug var state = db.Entry(activity).State; // Detached int activityCount = db.Activities.Local.Count; int projectCount = db.Activities.Local.Count; if (activityCount > 0 || projectCount > 0) throw new Exception("objects exist in dbcontext"); // end debug if (activity.ID == 0) db.Activities.Add(activity); else { db.Activities.Attach(activity); // throws here db.Entry(activity).State = System.Data.Entity.EntityState.Modified; } } return errorMsg; } public int ModifyProject(Presentation.PresProject presProject, out int id, out string errorMsg) { // snip foreach (PresActivity presActivity in presProject.Activities) { Activity a = presActivity.ToActivity(); // returns new Activity object errorMsg = ValidateActivity(a); // has no code yet. No. It does not query db. if (String.IsNullOrEmpty(errorMsg)) { a.Project = project; project.Activities.Add(a); AttachActivity(a); } else break; } if (string.IsNullOrEmpty(errorMsg)) { if (project.ID == 0) db.Projects.Add(project); else db.AttachAsModfied(project); saveCount = db.SaveChanges(); id = project.ID; } return saveCount; } 

Esta es la clase que las noticias hasta el dbContext:

 public void Try(Action work) { using(IServices client = GetClient()) // dbContext is newd up here { try { work(client); // ModifyProject is called here HangUp(client, false); } catch (CommunicationException e) { HangUp(client, true); } catch (TimeoutException e) { HangUp(client, true); } catch (Exception e) { HangUp(client, true); throw; } } 

No pregunto: ¿Cómo uso AsNoTracking? ¿Qué diferencia hace .AsNoTracking ()?

Una solución para evitar recibir este error es usar el método Find . antes de adjuntar la entidad, consulte DbContext para la entidad deseada, si existe una entidad en la memoria, obtendrá una entidad local, de lo contrario la entidad se recuperará de la base de datos.

 private void AttachActivity(Activity activity) { var activityInDb = db.Activities.Find(activity.Id); // Activity does not exist in database and it's new one if(activityInDb == null) { db.Activities.Add(activity); return; } // Activity already exist in database and modify it db.Entry(activityInDb).CurrentValues.SetValues(activity); db.Entry(activityInDb ).State = EntityState.Modified; } 

No se pudo adjuntar una entidad de tipo porque otra entidad del mismo tipo ya tiene el mismo valor de clave principal. Esto puede suceder cuando se usa el método Attach o se establece el estado de una entidad en Unchanged o Modified si alguna de las entidades en el gráfico tiene valores de clave en conflicto. Esto puede deberse a que algunas entidades son nuevas y aún no han recibido valores de clave generados en la base de datos. En este caso use el Add .

La solucion es que

Si tuvieras que usar GetAll ()

 public virtual IEnumerable GetAll() { return dbSet.ToList(); } 

Cambiar a

 public virtual IEnumerable GetAll() { return dbSet.AsNoTracking().ToList(); } 

Resolví este error cambiando el método de actualización como se muestra a continuación.

Si está utilizando un repository genérico y Entidad

 _dbContext.Set().AddOrUpdate(entityToBeUpdatedWithId); 

o normal (no genérico) repository y entidad, entonces

 _dbContext.Set().AddOrUpdate(entityToBeUpdatedWithId); 

Si usa el método AddOrUpdate (), asegúrese de haber agregado el espacio de nombres ” System.Data.Entity.Migrations “.