2

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!

vt100
  • 796
  • 6
  • 13

2 Answers2

2

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.

Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Code examples for the second approach (with DbContext though), just as additional reference: http://stackoverflow.com/q/5538974/270591 – Slauma May 19 '11 at 17:18
  • Thanks! That verifies what I thought... I had hoped that EF would prevent me from having to do state management like this. – vt100 May 19 '11 at 18:56
0

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

Milimetric
  • 13,411
  • 4
  • 44
  • 56