Estoy intentando implementar un AuditLog usando el objeto ChangeTracker de DBContext, encontré un problema donde el DbEntityEntry.OriginalValues
se borraba y se reemplazaba por el DbEntityEntry.CurrentValues
. Me llamó la atención que el problema era cómo estaba actualizando el objeto que estaba siendo rastreado en el DbContext (publicación original: Entity Framework DbContext SaveChanges() OriginalValue Incorrect).EF 4: Cómo actualizar adecuadamente el objeto en DbContext usando MVC con el patrón de repositorio
Así que ahora necesito ayuda para actualizar un objeto persistente utilizando el patrón de repositorio en MVC 3 con Entity Framework 4. Este código de ejemplo está adaptado de la aplicación SportsStore en el libro Pro Asp.NET MVC 3 Framework sacado por Apress.
Aquí es mi 'Editar' acción posterior en el AdminController:
[HttpPost]
public ActionResult Edit(Product product)
{
if (ModelState.IsValid)
{
// Here is the line of code of interest...
repository.SaveProduct(product, User.Identity.Name);
TempData["message"] = string.Format("{0} has been saved", product.Name);
return RedirectToAction("Index");
}
else
{
// there is something wrong with the data values
return View(product);
}
}
Esto pone en EFProductRepository clase concreta (que está implementando la interfaz IProductRepository y se inyecta a través de Ninject). Aquí está el método SaveProduct
en la clase repositorio concreto:
public void SaveProduct(Product product, string userID)
{
if (product.ProductID == 0)
{
context.Products.Add(product);
}
else
{
context.Entry(product).State = EntityState.Modified;
}
context.SaveChanges(userID);
}
El problema (como fue traído a mi atención en mi anterior SO post), es que cuando context.Entry(product).State = EntityState.Modified;
se llama de alguna manera arruina la capacidad de la ChangeTracker para informar sobre los cambios. Por lo tanto, en mi método DBContext.SaveChanges (string ID de usuario) sobrecargado, no veo valores exactos en el objeto ChangeTracker.Entries().Where(p => p.State == System.Data.EntityState.Modified).OriginalValues
.
Si actualizo mi método EFProductRepository.SaveProduct a este funciona:
public void SaveProduct(Product product, string userID)
{
if (product.ProductID == 0)
{
context.Products.Add(product);
}
else
{
Product prodToUpdate = context.Products
.Where(p => p.ProductID == product.ProductID).FirstOrDefault();
if (prodToUpdate != null)
{
// Just updating one property to demonstrate....
prodToUpdate.Name = product.Name;
}
}
context.SaveChanges(userID);
}
me gustaría saber la forma correcta para actualizar el objeto del producto y persistir en este escenario de tal manera que el ChangeTracker rastrea con precisión mis cambios a la clase POCO en el repositorio. ¿Se supone que debo hacer el último ejemplo (excepto, por supuesto, copiar todos los campos que pueden haber sido actualizados), o debería tomar un enfoque diferente?
En este ejemplo, la clase "Producto" es muy simple y solo tiene propiedades de cadena y propiedades decimales. En nuestra aplicación real, tendremos tipos "complejos" y las clases POCO harán referencia a otros objetos (es decir, a una persona que tenga una lista de direcciones). Sé que también podría necesitar hacer algo especial para rastrear los cambios en este caso. Quizás el conocimiento de esto cambie algunos consejos que recibo aquí.
Gracias por la respuesta. ¿Tienes un ejemplo de tu enfoque? Leí la pregunta SO a la que me vinculaste, pero todavía no estoy del todo claro. –
Ladislav, me acabo de dar cuenta de que nunca había seleccionado esto como la respuesta. Usted respondió mi pregunta original publicada y la agradezco. Además, tus muchas otras respuestas en stackoverflow a las preguntas de EF han sido increíblemente útiles para mí. Gracias de nuevo. –