Practical .NET

Mimic Lazy Loading with Entity Framework 6 and Entity Framework Core 1.1

Entity Framework Core doesn't have lazy loading (at least, not yet). But you can fake it by using explicit loading, though it doesn't work quite the way you might want. In fact, it's probably a good idea to use this in Entity Framework 6.

In an earlier column, I took a first look at what Entity Framework (EF) Core 1.0/1.1 does (and doesn't) do compared to EF6. One of the features that EF Core doesn't include is lazy loading. In EF6, thanks to lazy loading, if you touch a navigation property whose objects haven't yet been retrieved, Entity Framework automatically issues a call back to the database server to fetch those objects for you.

I'm not a big fan of lazy loading because, in most scenarios, I don't think it makes sense (I discussed when lazy loading might make sense in another column). But that doesn't mean you won't need it … or something like it when working with EF Core.

That "or something like it" is what the EF Core team calls "explicit loading," which is also available in EF6. Explicit loading also allows you to issue a query back to the database server to retrieve the objects in a navigation property. The reason it's called "explicit" is because, unlike lazy loading, you have to add a line of code to your application to trigger the query.

Here's some EF code that retrieves a collection of Customer objects and then, in the last line, uses explicit loading to populate the Customer object's Salesorders property:

using (db = new CustomerOrderContext())
{
  var custs = from cust in db.Customers
              where cust.Salesorders.Count() > 0
              select cust;
  foreach (Customer ct in custs)
  { 
    db.Entry(ct).Collection(cst => cst.Salesorders).Load();

Unfortunately, as written, this code won't work. When you get to the explicit loading line, you'll get an error that there already exists an Open DataReader on the connection and the query to retrieve your Salesorders won't be processed.

The workaround is to fully populate the custs collection by calling the ToList method on the query. Here's the code, revised:

using (db = new CustomerOrderContext())
{
  var custs = (from cust in db.Customers
               where cust.Salesorders.Count() > 0
               select cust).ToList();
  foreach (Customer ct in custs)
  { 
    db.Entry(ct).Collection(cst => cst.Salesorders).Load();
ToList both opens and closes the connection to the database (while retrieving your objects in between, of course), freeing up your connection to retrieve Salesorders later in your code.
comments powered by Disqus

Featured

  • What's Next for ASP.NET Core and Blazor

    Since its inception as an intriguing experiment in leveraging WebAssembly to enable dynamic web development with C#, Blazor has evolved into a mature, fully featured framework. Integral to the ASP.NET Core ecosystem, Blazor offers developers a unique combination of server-side rendering and rich client-side interactivity.

  • Nearest Centroid Classification for Numeric Data Using C#

    Here's a complete end-to-end demo of what Dr. James McCaffrey of Microsoft Research says is arguably the simplest possible classification technique.

  • .NET MAUI in VS Code Goes GA

    Visual Studio Code's .NET MAUI workload, which evolves the former Xamarin.Forms mobile-centric framework by adding support for creating desktop applications, has reached general availability.

  • Visual Studio Devs Quick to Sound Off on Automatic Updates: 'Please No'

    A five-year-old Visual Studio feature request for automatic IDE updates is finally getting enacted by Microsoft amid a lot of initial developer pushback, seemingly misplaced.

  • First Official OpenAI Library for .NET Goes Beta

    Although it seems Microsoft and OpenAI have been deeply intertwined partners for a long time, they are only now getting around to releasing an official OpenAI library for .NET developers, joining existing community libraries.

Subscribe on YouTube