locked
Entity Framework ObjectStateManager doesn't track all changes RRS feed

  • Question

  • I have a POCO that looks like this:

    public class Child { int Id; string Something; }

    and another one that looks like this:

    public class Parent { int Id; string Something; Child Child; }

    EF correctly discovers the relation between these two and the Parent table has a Child_Id foreign key column.

    The problem is, when I tap into the ObjectStateManager for auditing purposes, I can see when all the value type properties change on an entity (Id, Something, etc), but there are no references in the OriginalValues to the Child property. I spent half a day today inspecting the ObjectStateManager object in the debugger, hoping to find something that shows me when the reference to a Child object changes, but I couldn't find anything...

    Say, if my POCO has 10 properties, 7 are simple type values (int, string, Datetime, etc) and 3 are references to other POCO's, the OriginalValues array has only 7 elements, it's almost like all the related POCO's are not tracked. The updates work though, so obviously EF knows it has to issue a SQL UPDATE command, I just can't find the old value / new values for child-POCO's.

    Thanks in advance!

    Thursday, November 13, 2014 9:26 PM

Answers

  • Hello Florin,

    With your new description, I think I should understand this issue my opinion is that the team might place this change to a deeper location which the ObjectStateManager cannot see or just occurs on the database level.

    You could follow the this article to get the edmx file to see that the foreign key would be stored in SSDL and MSL, while CSDL does not contain a foreign key description. And the ObjectStateManager seems to track the CSDL only.

    So the workaround is you already mentioned to add the explicit foreign key. 

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Fred Bao Tuesday, November 25, 2014 8:25 AM
    Thursday, November 20, 2014 9:20 AM

All replies

  • Hello Florin,

    >>The updates work though, so obviously EF knows it has to issue a SQL UPDATE command, I just can't find the old value / new values for child-POCO's.

    According to your description, I made a test demo which could find the original/current values for child POCPs, you could check it below:

    using (DFDBEntities db = new DFDBEntities())
    
                {
    
                    ObjectStateManager obj = ((IObjectContextAdapter)db).ObjectContext.ObjectStateManager;
    
                    var order = db.Orders.FirstOrDefault();
    
                    order.OrderName = DateTime.Now.ToString();
    
                    var orderDetail = order.OrderDetails.FirstOrDefault();
    
                    orderDetail.OrderDetailName = DateTime.Now.ToString();
    
                    var ensureTracked = db.Entry(orderDetail).Property(o => o.OrderDetailName).OriginalValue;
    
                    var result = obj.GetObjectStateEntries(EntityState.Modified);
    
                    foreach (ObjectStateEntry entry in result)
    
                    {
    
                        if (entry.Entity is OrderDetail)
    
                        {
    
                            var columns = db.Entry((OrderDetail)entry.Entity).OriginalValues.PropertyNames.ToList();
    
                            foreach (string property in columns)
    
                            {
    
                                if (db.Entry((OrderDetail)entry.Entity).Property(property).IsModified)
    
                                {
    
                                    var origialValue = db.Entry((OrderDetail)entry.Entity).Property(property).OriginalValue;
    
                                    var currentValue = db.Entry((OrderDetail)entry.Entity).Property(property).CurrentValue;
    
                                }
    
                            }
    
                        }
    
                    }
    
                }
    

    If I misunderstand, please feel free let me know.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, November 14, 2014 3:06 AM
  • Thank you for replying and for taking your time to do this. I should have been a bit clearer. My use case is the one where the child object itself is replaced with another object. So, in your example, completely replace an OrderDetail object with another one.

    For example, if we had all the US states mapped to a State POCO and States table. Then an Address object would have a reference to a State object. On the UI, imagine picking the State from a drop-down.

    So, say I entered the state incorrectly and I must now edit my Address object and change the State to another one:

    address.State = dbContext.States.Find(7);
    dbContext.SaveChanges();

    In the Addresses table, the foreign key column state_id would be updated to the new state id of 7. But I can't find anything that reflects this change in the ObjectStateManager. You see, I didn't explicitly define a foreign key property for State in my Address class, I let EF do that for me automagically. I am guessing that if I define:

    int StateId { get; set; }

    in my Address class, the State Manager would catch the change from the old Id to the new Id. But I like not defining the foreign keys explicitly much better, it keeps the code cleaner and EF seems to handle it nicely... except for the change tracking...

    Friday, November 14, 2014 3:04 PM
  • Hello Florin,

    With your new description, I think I should understand this issue my opinion is that the team might place this change to a deeper location which the ObjectStateManager cannot see or just occurs on the database level.

    You could follow the this article to get the edmx file to see that the foreign key would be stored in SSDL and MSL, while CSDL does not contain a foreign key description. And the ObjectStateManager seems to track the CSDL only.

    So the workaround is you already mentioned to add the explicit foreign key. 

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Fred Bao Tuesday, November 25, 2014 8:25 AM
    Thursday, November 20, 2014 9:20 AM