En mi Editar acción del controlador, publico el objeto para actualizar.

 [HttpPost]
 public virtual ActionResult Edit(Case myCase){
      var currentDocuments = db.CaseDocuments.Where(p => p.idCase == myCase.idCase);

            foreach (CaseDocument docInDB in currentDocuments )
            {
                var deleteDoc = true;

                foreach (CaseDocument docNew in myCase.CaseDocuments )
                {
                    if (docNew.idDocument == docInDB.idDocument)
                        deleteDoc = false;
                }
                if (deleteDoc )
                    db.CaseDocuments.Remove(docInDB);
            }

            foreach (CaseDocument pc in myCase.CaseDocuments)
            {
                if (pc.idDocument == 0)
                    db.CaseDocuments.Add(pc);
                else
                    db.Entry(pc).State = EntityState.Modified;    
            }

           *** **db.Entry(myCase).State = EntityState.Modified;**  //THIS LINE
            db.SaveChanges();
 }

El modelo Case tiene una colección de Documents y se publican junto con el modelo de caso.

Tan pronto entro en acción, puedo contar la cantidad de documentos en la colección, y digamos que hay 3.

Luego, para ver si necesito eliminar documentos de la base de datos (ya que el usuario eliminó uno de la interfaz de usuario), necesito obtener los documentos para ese caso de la base de datos de esta manera:

var currentDocuments = db.CaseDocuments.Where(p => p.idCase == myCase.idCase);

Y aquí comienza lo extraño: tan pronto como ejecuto esa declaración, el myCase.Documents se carga con lo que está en la base de datos (digamos que hay 4) !! Por lo tanto, no puedo comparar las 2 colecciones (para detectar si se eliminó un documento y eliminarlo de la base de datos).

Lo que necesito es que durante la acción de edición de mi modelo de caso, necesito crear / actualizar / modificar sus documentos. ¿Necesito ver esto desde otro ángulo? ¿Qué estoy haciendo mal?

EDITAR: Luego de los comentarios, me di cuenta de que la línea donde marqué myCase como Modified, estaba al principio, y supongo que esa fue la razón de ese comportamiento.

Ahora, moviendo esa línea justo antes de db.SaveChanges (), solucionó ese problema, pero en db.Entry(myCase).State = EntityState.Modified; dice " Ya hay un objeto con la misma clave en ObjectStateManager. "

¿Qué estoy haciendo mal aquí? ¡Este código se ve mal!

0
Romias 22 abr. 2012 a las 21:48
Muestra todo el cuerpo de tu acción. Los documentos de su caso se cargarán solo si adjuntó previamente el caso al contexto utilizado para recuperar los documentos actuales.
 – 
Ladislav Mrnka
22 abr. 2012 a las 22:15
@LadislavMrnka, ahí está ... Todavía estoy probando diferentes enfoques, pero realmente no sé lo que estoy haciendo.
 – 
Romias
22 abr. 2012 a las 23:19

1 respuesta

La mejor respuesta

Pruébalo de esta manera:

 [HttpPost]
 public virtual ActionResult Edit(Case myCase){
     var currentDocumentIds = db.CaseDocuments
                                .Where(p => p.idCase == myCase.idCase)
                                .Select(p => p.idDocument);

     foreach (int idInDb in currentDocumentsIds.Where(i => !myCase.CaseDocuments
                                                                  .Any(ci => ci.idDocumnet == i))
     {
         var docToDelete = new CaseDocument { idDocument = idInDb };
         db.CaseDocuments.Remove(docToDelete);
     }

     foreach (CaseDocument pc in myCase.CaseDocuments)
     {
         if (pc.idDocument == 0)
            db.CaseDocuments.Add(pc);
         else
            db.Entry(pc).State = EntityState.Modified;    
     }

     db.Entry(myCase).State = EntityState.Modified;
     db.SaveChanges();
}

Editar: la diferencia entre este código y su código es la forma en que funciona con los documentos existentes. No los carga, solo carga sus identificadores. De esta manera, guardará algunas transferencias de datos de la base de datos, pero también debería ayudarlo a evitar esa excepción. Cuando carga el documento desde la base de datos, ya lo tiene adjunto en el contexto, pero si intenta llamar a esto:

db.Entry(pc).State = EntityState.Modified; 

Intentará adjuntar otra instancia del documento con la misma clave al contexto. Eso no está permitido: el contexto puede haber adjuntado una sola instancia con una clave única.

1
Ladislav Mrnka 23 abr. 2012 a las 17:39
¡Gracias !, pero ¿podrías explicar un poco qué (y por qué) estás haciendo esto de esta manera? Quiero decir, podría intentarlo y funcionaría, pero realmente necesito entender su "filosofía".
 – 
Romias
23 abr. 2012 a las 16:39
Agregué alguna explicación. Prueba el código y veremos si resuelve tu problema.
 – 
Ladislav Mrnka
23 abr. 2012 a las 17:39