ASP.NET MVC3 父子关系和Entity Framework,如何更新子项?

发布于 2024-11-08 10:50:42 字数 1129 浏览 0 评论 0原文

我有一个 ASP.NET MVC 3 应用程序,使用 Entity Framework 4 来处理数据访问。

我的视图模型对象结构如下所示:

public class OrderViewModel 
{
  public int Id { get; set; }
/* ... */
  public List<OrderLineItemViewModel> LineItems { get; set; }
}

public class OrderLineItemViewModel 
{
  public int Id { get; set; }
  public string Name { get; set; }
}

而且,我的实体框架模型如下所示:

public class Order 
{
  public int Id { get; set; }
/* ... */
  public List<OrderLineItem> LineItems { get; set; }
}

public class OrderLineItem
{
  public int Id { get; set; }
  public string Name { get; set; }
}

我正在努力解决的问题是如何处理编辑现有订单。我的控制器函数会将父视图模型转换为 Order 对象,并将子视图模型 (OrderLineItemViewModel) 转换为实体模型 (OrderLineItem)。但是,将实体附加到 ObjectContext 后,它会丢失已更改、添加或删除的行项目的状态。

我发现的所有解决父/子关系的示例似乎都主张不要对子集合进行级联更新,而是更喜欢使用单独的控制器操作和视图来更新子集合。但是,我试图将编辑作为一个原子操作进行...当用户点击“编辑订单”提交更改时,我希望更新父级的字段,并处理任何新的/删除的/修改的子级。 ..

从视图模型转换时,处理实体框架中子对象的更改跟踪的最佳方法是什么?

我尝试向 ViewModel 和 Model 添加 IsNew、IsDirty 和 IsDeleted,然后为每个子项调用适当的函数(附加、删除或添加),但是在尝试添加时出现错误,提示子项已存在于ObjectStateManager 处于 UnChanged 状态...

谢谢!

I have a ASP.NET MVC 3 application, using Entity Framework 4 to handle Data Access.

My View Model object structure looks like this:

public class OrderViewModel 
{
  public int Id { get; set; }
/* ... */
  public List<OrderLineItemViewModel> LineItems { get; set; }
}

public class OrderLineItemViewModel 
{
  public int Id { get; set; }
  public string Name { get; set; }
}

And, my Entity Framework Model looks like this:

public class Order 
{
  public int Id { get; set; }
/* ... */
  public List<OrderLineItem> LineItems { get; set; }
}

public class OrderLineItem
{
  public int Id { get; set; }
  public string Name { get; set; }
}

The thing that I am struggling with is how to handle editing an existing Order. My controller function will convert the Parent View Model into an Order object, and also convert the children (OrderLineItemViewModel) into the Entity Model (OrderLineItem). However, upon attaching the entity to the ObjectContext, it loses state of which Line Items have been changed, added, or deleted.

All of the examples that I have found that address parent/child relationships seem to advocate not doing cascading updates to children, rather, preferring to have a seperate Controller Action and View for updating the child collection. However, I am trying to have the edit happen as one atomic operation... When the user hits "Edit Order" to submit the changes, I want the parent's fields to update, as well as handle any new/deleted/modified children...

What's the best approach to handling change tracking on child objects in Entity Framework, when converting from a View Model?

I have tried adding a IsNew, IsDirty, and IsDeleted to the ViewModel and the Model, then calling the appropriate function for each child (Attach, Delete or Add), but I get errors when trying to add saying that the child alreadys exists in the ObjectStateManager in an UnChanged state...

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萝莉病 2024-11-15 10:50:42

您确实必须以某种方式告诉 EF 哪些内容发生了更改、添加了哪些内容以及删除了哪些内容。有两种方法:

  • 从视图模型创建 OrderOrderLines 并将 Order 实例附加到上下文。之后,您必须更改每个实体的状态 (context.ObjectStateManager.ChangeObjectState)。
  • 首先从数据库中使用 OrderLines 加载整个 Order ,然后将视图模型中的更改合并到附加的实体图 - 这就是我所使用的。

更复杂的描述位于另一个答案。当您使用多对多或一对多关系(其中相关实体可以更改父级)时,整个情况会变得更糟。

You must indeed somehow tell EF what has changed, what is added and what is deleted. There are two approaches:

  • Create your Order and OrderLines from your view models and Attach the Order instance to the context. After that you must change state of each entity (context.ObjectStateManager.ChangeObjectState).
  • Load the whole Order with OrderLines from the database first and then merge changes from view models to attached entity graph - that is what I use.

More complex description is in another answer. This whole become much worse when you work with many-to-many or one-to-many relations where related entities can change parent.

老娘不死你永远是小三 2024-11-15 10:50:42

只有两种方法可以找出发生了什么变化。

  1. 您可以使用 javascript 跟踪客户端的更改。这意味着当您发布表单时,您的 JavaScript 会拦截该帖子并将其与加载屏幕的原始数据进行比较。
  2. 您可以迭代子对象并将它们与控制器中的对象进行比较。如果有差异,您可以保存它们。

有一种方法可以在不知道发生了什么变化的情况下进行保存,这种方法可能会更有效。但是,它需要创建自定义查询并使用 TSQL 的 MERGE:

http://technet .microsoft.com/en-us/library/bb510625.aspx

There are only two ways to figure out what changed.

  1. You can track changes on the client side with javascript. This would mean that when you post the form, your javascript would intercept the post and compare it to the original data it loaded the screen with.
  2. You can iterate through the child objects and compare them to the objects from your controller. If there are differences, you can save them.

There is one way to save without knowing what changed that might be a little more efficient. However, it would require creating a custom query and using TSQL's MERGE:

http://technet.microsoft.com/en-us/library/bb510625.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文