gpt4 book ai didi

c# - EF 4 : How to properly update object in DbContext using MVC with repository pattern

转载 作者:IT王子 更新时间:2023-10-29 04:42:20 25 4
gpt4 key购买 nike

我正在尝试使用 DBContext 的 ChangeTracker 对象实现 AuditLog,我遇到了 DbEntityEntry.OriginalValues 被清除并替换为 DbEntityEntry.CurrentValues 。我注意到问题是如何更新在 DbContext 中跟踪的对象(原帖:Entity Framework DbContext SaveChanges() OriginalValue Incorrect)。

所以现在我需要一些帮助,以正确的方式使用 MVC 3 和 Entity Framework 4 中的存储库模式更新持久对象。此示例代码改编自 Pro Asp.NET MVC 3 Framework 书中的 SportsStore 应用程序由 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 接口(interface)并通过 Ninject 注入(inject))。下面是具体存储库类中的 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 类将引用其他对象(即具有地址列表的人)。我知道我可能还需要做一些特别的事情来跟踪这种情况下的变化。也许对此的了解会改变我在这里收到的一些建议。

最佳答案

it somehow messes up the ChangeTracker's ability to report on the changes

不,它不会弄乱任何东西。变更跟踪器能力基于这样一个事实,即变更跟踪器在进行更改之前就知道实体。但在您的情况下,更改跟踪器会获悉已应用更改的实体,而 POCO 实体不会保留有关其原始值的任何信息。 POCO 实体只有一组值,这些值被解释为当前值和原始值。如果您想要其他任何东西,您必须自己编写代码。

Am I supposed to do the latter example

在您的简单情况下是的,您可以简单地使用:

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)
{
context.Entry(prodToUpdate).CurrentValues.SetValues(product);
}
}

context.SaveChanges(userID);
}

问题是这只适用于简单和复杂的属性。另一个问题是这会覆盖所有属性,因此如果您的实体有一些您不想在 UI 中显示的字段(或者不想让用户编辑该字段),您仍然必须为您的 product 实例,否则在应用当前值时该值将被覆盖。

整个情况变成significantly more complex一旦您尝试将其应用于真实场景。在编写大量代码来准确支持您的案例之前,您会失败并且会失败很多次,因为可能没有通用的解决方案 EF 没有针对这种情况的支持方法。原因是 EF 为每个实体和一些关联都有内部状态机,您必须为要更新、插入或删除的每个实体或关联配置状态,并且必须按照 EF 内部规则进行配置。设置实体的状态将改变单个实体的状态,但不会改变它的关系。

我只是通过加载当前实体与数据库中的所有关系并手动(在代码中)合并整个实体图(简单地说,您已经分离和附加实体图,并且您必须将所有更改从分离的转移到附加的实体图)。

关于c# - EF 4 : How to properly update object in DbContext using MVC with repository pattern,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9591165/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com