Я пытаюсь реализовать AuditLog, используя объект ChangeTracker DBContext, я столкнулся с проблемой, когда DbEntityEntry.OriginalValues
стирались и заменялись DbEntityEntry.CurrentValues
. Мне стало известно, что проблема была как Я обновлял объект, который отслеживался в DbContext (оригинальное сообщение: Entity Framework DbContext SaveChanges () OriginalValue Inclusive ).
Так что теперь мне нужна помощь в правильном способе обновления персистентного объекта с использованием шаблона репозитория в MVC 3 с Entity Framework 4. Этот пример кода адаптирован из приложения SportsStore в книге Pro Asp.NET MVC 3 Framework. вне 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 в хранилище. Должен ли я сделать последний пример (кроме, конечно, копирования всех полей, которые могли быть обновлены), или я должен использовать другой подход?
В этом примере класс «Product» очень прост и имеет только строковые свойства и десятичные свойства. В нашем реальном приложении у нас будут «сложные» типы, а классы POCO будут ссылаться на другие объекты (т.е. на человека, у которого есть список адресов). Я знаю, что мне также может понадобиться сделать что-то особенное, чтобы отслеживать изменения в этом случае. Возможно, знание этого изменит некоторые советы, которые я получу здесь.