none
Retrieving from ObjectStateManager the parent reference of a deleted entity

    Question

  • Hi all!
    I'm trying to figure out the following but... I'm probably missing something!

    Let's say that we have the classic Customer-Order relation example.
    If I change some value in an order entity, I can use the ObjectStateManager to retrieve the original value using the following code:
    Dim objectStateEntry = context.ObjectStateManager.GetObjectStateEntry(myOrder.EntityKey)
    Dim originalValue = objectStateEntry.OriginalValues.GetValue(...)

    Here is the problem. I delete an order and therefor the order is detached from the parent Customer. I can still get the Object State Entry using the ObjectStateManager. But I cannot figure out how I can get from the ObjectStateEntry the Customer entity that the Order was related to before the Order was deleted. Ofcourse the Order.Customer and Order.CustomerReference are empty and the OriginalValues collection does not contain any information about the "Original Value" of the order's Customer or CustomerReference property.

    Any ideas?
    Friday, October 10, 2008 9:16 PM

Answers

  • When the Order entity is deleted, its relationships are also deleted.  This makes it difficult to get the Customer to which it was previously related.  However, the ObjectStateManger does still contain an entry for the deleted relationship and it is possible to use these to find the Customer entity.  The process is somewhat convoluted because it is not easy to find the correct relationship in the ObjectStateManager.  Here is some code that does it:

     

    var order = (from o in context.Orders select o).First();

    context.DeleteObject(order);

     

    var customerKey = (from e in context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted)

                                 where e.IsRelationship &&

                                          e.EntitySet.Name == "FK_Orders_Customers" &&

                                          (EntityKey)e.OriginalValues[1] == order.EntityKey

                                 select (EntityKey)e.OriginalValues[0]).FirstOrDefault();

     

    var customer = context.GetObjectByKey(customerKey);

     

    (Sorry that the code is in C#.  Hopefully it is still possible to follow what is going on.)

     

    First I query for an order and delete it, just to set things up for the example.

     

    Next, I execute a LINQ to Objects query over all the deleted entries in the ObjectStateManager.  The query asks for all entries that represent relationships, that have the relationship name that I am interested in, and that have one key of that relationship matching the Order key.  (Note that the OriginalValues for an relationship entry are the the keys at either end of the relationship.)  I project the Customer key as the result of the query.

     

    Finally, I can use the customer key to get the Customer entity.

     

    If any of that doesn't make sense, feel free to post again, and I will try to explain more.

     

    Also, Danny Simmons wrote some extension methods to do this kind of thing (and more) in blog posts relating to his EntityBag sample.  Go to http://code.msdn.com/entitybag and look at the blog post links from there for more information.

     

    Thanks,

    Arthur

     

    Saturday, October 11, 2008 12:00 AM

All replies

  • When the Order entity is deleted, its relationships are also deleted.  This makes it difficult to get the Customer to which it was previously related.  However, the ObjectStateManger does still contain an entry for the deleted relationship and it is possible to use these to find the Customer entity.  The process is somewhat convoluted because it is not easy to find the correct relationship in the ObjectStateManager.  Here is some code that does it:

     

    var order = (from o in context.Orders select o).First();

    context.DeleteObject(order);

     

    var customerKey = (from e in context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted)

                                 where e.IsRelationship &&

                                          e.EntitySet.Name == "FK_Orders_Customers" &&

                                          (EntityKey)e.OriginalValues[1] == order.EntityKey

                                 select (EntityKey)e.OriginalValues[0]).FirstOrDefault();

     

    var customer = context.GetObjectByKey(customerKey);

     

    (Sorry that the code is in C#.  Hopefully it is still possible to follow what is going on.)

     

    First I query for an order and delete it, just to set things up for the example.

     

    Next, I execute a LINQ to Objects query over all the deleted entries in the ObjectStateManager.  The query asks for all entries that represent relationships, that have the relationship name that I am interested in, and that have one key of that relationship matching the Order key.  (Note that the OriginalValues for an relationship entry are the the keys at either end of the relationship.)  I project the Customer key as the result of the query.

     

    Finally, I can use the customer key to get the Customer entity.

     

    If any of that doesn't make sense, feel free to post again, and I will try to explain more.

     

    Also, Danny Simmons wrote some extension methods to do this kind of thing (and more) in blog posts relating to his EntityBag sample.  Go to http://code.msdn.com/entitybag and look at the blog post links from there for more information.

     

    Thanks,

    Arthur

     

    Saturday, October 11, 2008 12:00 AM
  • Thanks Arthur! This is great and C# is not a problem at all.

    But since you mention it, I gave up the idea using EntityBag some time ago. I saw that there hasn't been a release from January 08, although there are braking changes in EF in its final release. Do you have any indication that this is still a viable project?

    Saturday, October 11, 2008 8:27 AM
  • EntityBag is not something I would ever have recommended for a production product.  It was designed to be a sample that you can use to learn more about how the EF works.  The valuable part is the series of blog posts explaining different aspects/principles which are still valid.

     

    - Danny

    Sunday, October 12, 2008 5:06 AM