Tuesday, January 31, 2012

LINQ to Entities, ObjectDisposedException, and Lazy Loading

Consider this code:
List<Product> redProducts = null;
using (var ctx = new AdventureWorksContext())
{
    redProducts = ctx.Products.Where(p => p.Color == "Red").ToList();
}

foreach (var p in redProducts)
{
    Console.WriteLine("{0}: {1}", p.Name, p.ProductCategory.Name);
}
At run time, I get an exception:
Unhandled Exception: System.ObjectDisposedException:
The ObjectContext instance has been disposed and
can no longer be used for operations that require
a connection.
Notice that when iterating over the redProducts, I am accessing the ProductCategory navigation property. In Entity Framework 4.0, lazy loading is enabled by default. This means that when I access the ProductCategory property, the entity tries to retrieve the ProductCategory row from the database. However, I am outside of the using block, so the entity context has already been disposed.

One solution in this case is to simply eager load all the data I need before the entity context is disposed.
redProducts = ctx.Products.Include("ProductCategory").Where(p => p.Color == "Red").ToList();
Or, I could just pull down the two pieces of data that I need:
IList redProducts = null;
using (var ctx = new AdventureWorksContext())
{
    redProducts = ctx.Products.Where(p => p.Color == "Red")
                     .Select(p => new { p.Name, Category = p.ProductCategory.Name })
                     .ToList();
}

foreach (dynamic p in redProducts)
{
    Console.WriteLine("{0}: {1}", p.Name, p.Category);
}

No comments:

Post a Comment