EF 4: Как правильно обновить объект в DbContext с помощью MVC с шаблоном репозитория

Я пытаюсь реализовать AuditLog с помощью объекта ChangeTracker DBContext, я столкнулся с проблемой, когда DbEntityEntry.OriginalValuesстирались и заменялись DbEntityEntry.CurrentValues. Мое внимание привлекла проблема в том, какя обновлял объект, отслеживаемый в DbContext (исходное сообщение: Entity Framework DbContext SaveChanges() OriginalValue Incorrect).

Итак, теперь мне нужна помощь в правильном способе обновления сохраняемого объекта с использованием шаблона репозитория в 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 в репозитории. Должен ли я сделать последний пример (за исключением, конечно, копирования всех полей, которые могли быть обновлены), или я должен использовать другой подход?

В этом примере класс «Продукт» очень прост и имеет только строковые свойства и десятичные свойства. В нашем реальном приложении у нас будут «сложные» типы, а классы POCO будут ссылаться на другие объекты (например, на человека, у которого есть список адресов). Я знаю, что мне также может понадобиться сделать что-то особенное, чтобы отслеживать изменения в этом случае. Возможно, знание этого изменит некоторые советы, которые я здесь получаю.

19
задан Community 23 May 2017 в 12:33
поделиться