[MVC 3] Entity Framework 4–Disposing ObjectContext–TIP


ADO.NET Entity Framework stack

Image via Wikipedia

The Entity Framework can throw a lot of Exceptions depending on what you are trying to achieve. We are lucky that the default CRUD controller template includes how to use EF during a Create/Delete/Edit scenario, but sometimes (a lot of the time in my case), when you first begin using EF, the exceptions keep on coming.

 

A lot of people use either try/finally or using statements when using their ObjectContext. You will find a lot of people will have something like (db being the ObjectContext):

 

    finally {
        if (db != null)
 db.Dispose();
    }

}

 

 

Now this is fine, but you need to handle this correctly, because if you saves changes after this, you could throw an InvalidOperationException, with the following text:

 

The object cannot be attached because it is already in the object context. An object can only be reattached when it is in an unchanged state.

OR

 

 

ObjectDisposedException

 

In Entity Framework, entities are attached to the EF context and changes are “tracked” within the framework. So you need to make sure you are not trying to Attach or Detach your entities incorrectly. Remember:

 

AddObjectUsed solely to add new entities only (Does not deal with EntityState.Modified items) to the context to be added to the data source.

AttachUsed to update an object that already exists in the context.

 

Now if we Dispose the object context incorrectly, then this could cause the above exceptions to be thrown later on when trying to update the data sources after the finally statement which includes the Dispose.

 

Now the way i get around this is use partial to extend my EF ObjectContext class (in my case EduEntities), and override the Dispose method so i only Detach the Unchanged Entities.

 

public partial class EduEntities {
    protected override void Dispose(bool disposing)
    {

        foreach (var entry in ObjectStateManager.GetObjectStateEntries       (EntityState.Unchanged))
        {

            Detach(entry.Entity);
        }

        base.Dispose(disposing);

    }

}

 

This means that the tracking on my changed objects are not lost.

Enhanced by Zemanta