Caution when Eager Loading in the Entity Framework

  • Dec 28, 2008 at 4:36 PM
  • Shawn Wildermuth
  • 9 Comments

Url: http://code.msdn.microsoft.com/EFExtensions

Silverlight Logo

UPDATE: Roger Jennings correctly stated, I meant to say that Include is *not* a guarantee.

When I am using the Entity Framework for a project, I have gotten into the habit of using eager loading via the Include syntax. In case you're not familiar it, the Entity Framework has a different philosophy than other data layers (e.g. NHibernate). In the Entity Framework, relationships have to be manually loaded when they are lazy loaded (so developers never have network round-trips without explicitly knowing about it). Whether you agree or not with this philosophy, understanding how it works is helpful when you're working with the Entity Framework.

The Entity Framework supports eager loading of the data as well using the Include syntax.  For example:

var qry = from w in ctx.Workshops.Include("Topic")
          orderby w.Name
          select w;

By amending the source of the query with the Include method, you can eager load relationships.  The problem is that these are really hints to the Entity Framework to load the relationships, but not a guarantee.  Depending on the query, these Includes may be dropped. The two scenarios I see this most often are the grouping and subselects:

// Drops the Include
var qry = from e in ctx.Events
                       .Include("Workshop")
          where e.EventDate >= DateTime.Today
          group e by e.EventLocation.Region into r
          select r;

I ran into a good post on the forums on the subject:

In that post, Diego Vega says that Include only makes sense in the following scenarios:

  • Include only applies to items in the query results: objects that are projected at the outermost operation in the query, for instance, the last Select() operation (in your query, you tried to apply Include to a subquery)
  • The type of the results has to be an entity type (not the case in your query)
  • The query cannot contain operations that change the type of the result between Include and the outermost operation (i.e. a GroupBy() or a Select() operation that changes the result type)
  • The parameter taken by Include is a dot-delimited path of navigation properties that have to be navigable from an instance of the type returned at the outermost operation

To alleviate the problem in some scenarios, you can use the EFExtensions Include Extension method to add includes on the complete query like so:

using Microsoft.Data.Extensions;
// ...
var qry = from e in ctx.Events
          where e.EventDate >= DateTime.Today
          select e;

List results = qry.Include("Workshop").ToList();

You can find the EFExtensions at the MSDN Code site here:

Has this bitten you before?

 

Comments

Gravatar

Roger Jennings Monday, December 29, 2008

Shawn,

I believe you meant to say "not a guarantee" rather than "a guarantee" in your post. Also, the link to the forum thread you quoted is broken.

See the first item in http://oakleafblog.blogspot.com/2008/12/linq-and-entity-framework-posts-for_22.html for details.

Cheers,

--rj

Gravatar

Roger Tuesday, December 30, 2008

Shawn

Do you really think that LINQ for Entities will be widely adopted by regular .NET developers like ADO.NET, or it will just be another of Microsoft's quick recipes looking for a small niche and eventually being replaced with something else?

Regards

RT.

Gravatar

Shawn Wildermuth Tuesday, December 30, 2008

RT,

Microsoft has made a major investment in the Entity Framework and I really think that the v2 version will tell the story of whether it succeeds or not. I don't think its going away and is built on top of ADO.NET (much like NHibernate and other ORMs).

Gravatar

Roger Tuesday, December 30, 2008

I hope you are right, although this is not the feedback I'm getting from many dev groups. Like Hibernate (and clones), this solution is too complex and takes too much time to get it right. With ADO.NET you can build a decent DAL and move on. We'll see what happens with v2.

Cheers

RT.

Gravatar

Shawn Wildermuth Tuesday, December 30, 2008

RT,

Honestly, there is a current hole in EF that makes it hard to work with in n-Tier scenarios that they are filling, but other than that I find it easier to get a EF model up and running than NHibernate. For web apps right now EF does a good job of a DAL layer though it not perfect. If NHibernate had a decent designer, i'd probably be running it instead.

Gravatar

Ayende Rahien Thursday, January 08, 2009

Shawn, take a look at Active Writer.

Gravatar

Jeff Wednesday, January 14, 2009

I seem to be getting the same problem when performing a join between two entities. The Include is ignored.

I have had to use the Load method for now :(

Cheers

Jeff

Gravatar

Eric Duncan Monday, May 16, 2011

List results = qry.Include("Workshop").ToList();

Man, been chasing that one down for a while. Thanks!

Gravatar

Nishant Friday, November 04, 2011

Hi Roger,
I ran one query but in case collection nothing comes but i saw there is value for case, below is the query, can you please let me know what the wrong i am doing.

DateTime dtNow = Convert.ToDateTime(DateTime.Now.ToShortDateString());

using (commonContext = new TheraCallContext())
{
resOrder = (from Order OM in commonContext.Orders.Include("Case")
join Case CM in commonContext.Cases on OM.CaseId equals CM.CaseId
where CM.PatientId == ptntId && EntityFunctions.TruncateTime(OM.CreatedDate).Value >= dtNow && (OM.DeleteFlag == null || !(OM.DeleteFlag == true))
orderby OM.CreatedDate descending
select OM).Take(1).ToList();



Leave a Comment

*
*
*