Sto tentando di implementare un AuditLog utilizzando l'oggetto ChangeTracker di DBContext, ho riscontrato un problema in cui lo DbEntityEntry.OriginalValues
veniva cancellato e sostituito con DbEntityEntry.CurrentValues
. È stato portato alla mia attenzione che il problema era come stavo aggiornando l'oggetto che veniva monitorato nel DbContext (post originale: Entity Framework DbContext SaveChanges() OriginalValue Incorrect).EF 4: Come aggiornare correttamente l'oggetto in DbContext utilizzando MVC con pattern di repository
Quindi ora ho bisogno di aiuto sul modo corretto di aggiornare un oggetto persistente utilizzando il modello di repository in MVC 3 con Entity Framework 4. Questo codice di esempio viene adattato dall'applicazione SportsStore nel libro Pro Asp.NET MVC 3 Framework messo fuori da Apress.
Ecco il mio 'Modifica' azione posta in 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);
}
}
Questo chiama in EFProductRepository classe concreta (che sta attuando l'interfaccia IProductRepository e iniettato attraverso Ninject). Ecco il metodo SaveProduct
nella classe repository concreta:
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);
}
Il problema (come è stato portato alla mia attenzione nel mio precedente SO post), è che quando context.Entry(product).State = EntityState.Modified;
si chiama si scombina in qualche modo fino capacità del ChangeTracker di riferire in merito i cambiamenti. Quindi nel mio metodo DBContext.SaveChanges (stringa userID) sovraccarico, non vedo valori precisi nell'oggetto ChangeTracker.Entries().Where(p => p.State == System.Data.EntityState.Modified).OriginalValues
.
Se aggiorno il mio metodo EFProductRepository.SaveProduct a questo funziona:
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);
}
Vorrei sapere il modo corretto per aggiornare l'oggetto prodotto e persistono in questo scenario in modo tale che il ChangeTracker traccia accuratamente le mie modifiche alla classe POCO nel repository. Dovrei fare l'ultimo esempio (eccetto ovviamente copiare tutti i campi che potrebbero essere stati aggiornati) o dovrei adottare un approccio diverso?
In questo esempio la classe "Prodotto" è molto semplice e ha solo proprietà di stringa e proprietà decimali. Nella nostra applicazione reale avremo tipi "complessi" e le classi POCO faranno riferimento ad altri oggetti (ad esempio, Persona che ha un elenco di indirizzi). So che potrebbe anche essere necessario fare qualcosa di speciale per tenere traccia delle modifiche in questo caso. Forse la conoscenza di questo cambierà alcuni consigli che ricevo qui.
Grazie per la risposta. Hai un esempio del tuo approccio? Ho letto la domanda SO a cui ti sei collegato, ma non sono ancora del tutto chiaro. –
Ladislav, mi sono appena reso conto che non avevo mai scelto questo come risposta. Hai risposto alla mia domanda postata originale e lo apprezzo. Inoltre, le molte altre risposte sullo stackoverflow alle domande EF sono state incredibilmente utili per me. Grazie ancora. –