Я пытаюсь реализовать AuditLog с помощью объекта DBContext ChangeTracker, я столкнулся с проблемой, когда DbEntityEntry.OriginalValues
были уничтожены и заменены на DbEntityEntry.CurrentValues
. Мне было доведено до сведения, что проблема заключалась в том, как я обновлял объект, который отслеживался в DbContext (исходное сообщение: Entity Framework DbContext SaveChanges() OriginalValue Неверно).
Итак, теперь мне нужна помощь по правильному способу обновления сохраненного объекта с использованием шаблона репозитория в MVC 3 с Entity Framework 4. Этот примерный код адаптирован из приложения SportsStore в книге Pro Asp.NET MVC 3 Framework put из Apress.
Вот мое действие "Изменить" в 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);
}
}
Это вызывает конкретный класс EFProductRepository (который реализует интерфейс IProductRepository и вводится через Ninject). Ниже приведен метод SaveProduct
в конкретном классе репозитория:
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);
}
Проблема (как было доведена до моего внимания в моей предыдущей SO-почте), заключается в том, что когда context.Entry(product).State = EntityState.Modified;
называется, она каким-то образом помещает способность ChangeTracker сообщать об изменениях. Поэтому в моем перегруженном методе DBContext.SaveChanges(string userID) я не вижу точных значений в объекте ChangeTracker.Entries().Where(p => p.State == System.Data.EntityState.Modified).OriginalValues
.
Если я обновляю свой метод EFProductRepository.SaveProduct, он работает:
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);
}
Я хотел бы знать, как правильно обновлять объект Product и сохранять его в этом сценарии таким образом, что ChangeTracker точно отслеживает мои изменения в классе POCO в репозитории. Должен ли я использовать последний пример (за исключением, конечно, копирования всех полей, которые могли быть обновлены), или я должен придерживаться другого подхода?
В этом примере класс "Продукт" очень прост и имеет только свойства строки и десятичные свойства. В нашем реальном приложении у нас будут "сложные" типы, а классы POCO будут ссылаться на другие объекты (т.е. Лицо, имеющее список адресов). Я знаю, что мне может понадобиться сделать что-то особенное, чтобы отслеживать изменения в этом случае. Возможно, знание об этом изменит некоторые советы, которые я получаю здесь.