Migrating from LINQ to SQL to Entity Framework: Deferred Loading

Last week, we covered Eager Loading and how to migrate LINQ to SQL based code that took advantage of Eager Loading. This week, we discuss Deferred Loading.

Generally speaking, queries only retrieve the objects you request, and not their related objects. Deferred Loading (or Lazy Loading) allows you to automatically load objects on demand if and when you attempt to access the object that is not yet loaded (you might do this by trying to access a property that allows you to get to the object you are interested in, for instance).

Automatic Deferred Loading has its advantages and disadvantages – automatic deferred loading that is on by default means more productivity and less code to write. However, it also means less control over when and how you hit the database. In LINQ to SQL, Automatic Deferred Loading is enabled by default, but it can be disabled by using the following code fragment. For more information, see Deferred versus Immediate Loading (LINQ to SQL).

 db.DeferredLoadingEnabled = false;

In the example below, you are really only querying for  objects from the Products table – however, because Deferred Loading is enabled, you can access prod.SalesOrderDetail (which automatically fetches the associated SalesOrderDetail values from the database, and surfaces the results as SalesOrderDetail objects for the particular product)

 var products = from prod in db.Products
               where prod.Color == "Blue"
               select prod;

foreach (Product prod in products)
{
    foreach (SalesOrderDetail detail in prod.SalesOrderDetail)
    {
        // do something with detail
    }
}

The Entity Framework does not provide an automatic mechanism for deferred loading.  However, a simple addition to the code above achieves the same result.

 var products = from prod in db.Product
               where prod.Color == "Blue"
               select prod;

foreach (Product prod in products)
{
    // avoids unnecessary queries
    if (!prod.SalesOrderDetail.IsLoaded)
    {
        prod.SalesOrderDetail.Load();
    }

    foreach (SalesOrderDetail detail in prod.SalesOrderDetail)
    {
        // do something with detail
    }
}

For more information, see Navigation Properties. Also see Jaroslaw Kowalski’s blog series Transparent Lazy Loading for Entity Framework which discusses the EFLazyClassGen samples available on CodeGallery.  EFLazyClassGen could also be extended to support a Link<T> style deferred loading of individual properties.

In our next post, we will look at Stored Procedures. Stay tuned and let us know what you think!

- The ADO.NET Team