find a location for property in a new city

Friday, 18 March 2011

How to update a detached entity in Entity Framework

If you are using Entity Framework and closing or disposing of your DataContexts (read database connections) as soon as your Linq to Entities query have finished, which I believe you should, you will run into the situation where saving changes to an updated entity will be ineffectual.

I've discussed before that I think deliberately keeping database connections open is bad in Entity Framework but when practicing this technique you will find saving changes to an updated entity no longer works as it used to when the DataContext was left open as long as it liked.

This is because when you open a DataContext you are also starting up change tracking. Change tracking will keep a note of if your entity has been changed. This is important when you call SaveChanges on that DataContext because it needs to know if there have been any changes to save.

If, however, you open your DataContext, do you Linq to Entities query to get an entity and then dispose of your DataContext your entity is now detached. To SaveChanges you will need to open an new DataContext, which will have no idea that this entity has been changed. So you need a way to update a detached Entity.

Update a detached entity with your DataContext

You can do this by using the Attach method to attach this entities to the DataContext (so it is now managing it). After you've attached it it will be in the "Unchanged" state so will not do anything on SaveChanges. You can tell it it has been updated by changing its object state to Modified. Then simply save changes.

Here is an example. (This is not my actual code - it is more explicit to aid understanding):

public void UpdateObject(T obj)
{
    using (var context = new MyDataContext())
    {
        context.CreateObjectSet<T>().Attach(obj);
        context.ObjectStateManager.ChangeObjectState(obj, EntityState.Modified);
        context.SaveChanges();
    }
}

Updating a detached model when using EF Code First

Coming back to my blog years later (Feb 2013) to reuse the above code I found it didn't work in Entity Framework Code First Model. This is because the context mentioned above is a different from the DbContext used in Code First and so has different properties and methods. Here is the code I used to make this work in EF Code First:

public void UpdateObject(T obj)
{
    using (var context = new MyDataContext())
    {
        context.Set<T>().Attach(obj);
        context.ChangeTracker.Entries<T>().First(e => e.Entity == obj)
                                              .State = EntityState.Modified;
        context.SaveChanges();
    }
}

Follow britishdev on Twitter

1 comment:

  1. Thank you, this works like a charm and best of all I understand what i'm doing with all the guff involved in Entity framework to account for.

    ReplyDelete