Near Infinity

Type-Safe Entity Framework Include

By Joe Ferner

Nov 18, 2010

Unlike many ORM solutions MS Entity Framework does not lazy fetch accessed tables. Coming from LINQ to SQL I didn't like this feature at first because it meant adding a bunch of loosely typed include statements to every SQL call. But I quickly realized the performance benefits, not to mention theN+1 problem just goes away. But, I still had heartburn over the loose typing of the include statement, so I came up with my own include. But first to set the stage let me show you what you currently have to write.

  ctx.Users.Include("Order.Item");

This will fetch all Users as well as all the items that they ordered.

To fix this we need to add some method to Users which is of type ObjectQuery. To do that we will use extension methods to add my own include to ObjectQuery. Here is the code for that.

public static class ObjectQueryExtensionMethods {
  public static ObjectQuery<T> Include<T>(this ObjectQuery<T> query, Expression<Func<T, object>> exp) {
    Expression body = exp.Body;
    MemberExpression memberExpression = (MemberExpression)exp.Body;
    string path = GetIncludePath(memberExpression);
    return query.Include(path);
  }
 
  private static string GetIncludePath(MemberExpression memberExpression) {
    string path = "";
    if (memberExpression.Expression is MemberExpression) {
      path = GetIncludePath((MemberExpression)memberExpression.Expression) + ".";
    }
    PropertyInfo propertyInfo = (PropertyInfo)memberExpression.Member;
    return path + propertyInfo.Name;
  }
}

Using C# expressions and extension methods we now can write this

  ctx.Users.Include(u => u.Order.Item);

Refactor and type-safe

Entity Framework still has it's annoyances, but hopefully this will make it a little less painful. Now if it would only throw an exception if you tried to access a non-included entity instead of just returning null.