Eager Loading with Repository Pattern and Entity Framework

June 22, 2010

Eager Loading with Repository Pattern and Entity Framework


One question that I Eager Loading with Repository Pattern and Entity Framework
received yesterday
after I published the
Revisiting the Repository 
and Unit of Work Patterns

with Entity Framework
post was
how to include the eager loading
ability of Entity Framework.
This post is offering a solution.


Revisiting Eager Loading and Lazy Loading


Lazy loading is a design pattern that is commonly used to defer
initialization of an object up until it is needed by the program.
The gains of using the pattern include efficiency (if it’s used right)
and sometime performance. Eager loading is the opposite pattern of
lazy loading
. In this pattern we initialize the object before hand and
don’t wait to the second we really need it.
In Entity Framework we can use the Include method in order to
eager load an entity graph.


Eager Loading with Repository Pattern


In the interface of the Repository I will add a new method which
will be called QueryObjectGraph. That method will receive a string
which indicate the children to load. Now the interface will look like:



public interface IRepository<T> where T : class
{        
    T GetById(int id);
    IEnumerable<T> GetAll();
    IEnumerable<T> Query(Expression<Func<T, bool>> filter);
    IEnumerable<T> QueryObjectGraph(Expression<Func<T, bool>> filter, string children);
    void Add(T entity);
    void Remove(T entity);   
}

and the implementation of the abstract Repository will change to



public abstract class Repository<T> : IRepository<T>
                                  where T : class
{
  #region Members
 
  protected ObjectSet<T> _objectSet;
 
  #endregion
 
  #region Ctor
 
  public Repository(ObjectContext context)
  {
    _objectSet = context.CreateObjectSet<T>();
  }
 
  #endregion
 
  #region IRepository<T> Members
 
  public IEnumerable<T> GetAll()
  {
    return _objectSet;
  }
 
  public abstract T GetById(int id);
 
  public IEnumerable<T> Query(Expression<Func<T, bool>> filter)
  {
    return _objectSet.Where(filter);
  }
 
  public IEnumerable<T> QueryObjectGraph(Expression<Func<T, bool>> filter, string children)
  {
    return _objectSet.Include(children).Where(filter);
  }
 
  public void Add(T entity)
  {
    _objectSet.AddObject(entity);
  }
 
  public void Remove(T entity)
  {
    _objectSet.DeleteObject(entity);
  }
 
  #endregion
}

Pay attention that I replaced the IObjectSet<T> into it’s
Entity Framework implementation of ObjectSet<T>. The reason
is that the IObjectSet<T> interface doesn’t include the Include method.
Now I can continue using the same Unit of Work implementation and
also use the eager loading ability like in the following example:



using (SchoolEntities context = new SchoolEntities())
{
  UnitOfWork uow = new UnitOfWork(context);
  foreach (var department in uow.Departments.GetAll())
  {
    Console.WriteLine(department.Name);
  }
 
  foreach (var department in uow.Departments.Query(d => d.Budget > 150000))
  {
    Console.WriteLine(“department with above 150000 budget: {0}”,
        department.Name);
  }
 
  foreach (var department in uow.Departments.QueryObjectGraph(d => d.Budget > 150000, “Courses”))       
  {
    Console.WriteLine(“department with above 150000 budget: {0}, {1}”,
        department.Name, department.Courses.First().Title);
  }
}

Summary


In the previous post I only showed the way to implement your
repositories. As you can see in this post I can take the offered
solution and make it specific to my needs.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

5 comments

  1. James AlexanderJune 22, 2010 ב 16:48

    Thanks for the follow up! I definitely like the idea of breaking it out into a seperate function as you’ve done w/ QueryObjectGraph. How would this account for eager loading multiple navigation properties though?

    Reply
  2. Gil FinkJune 24, 2010 ב 8:13

    @James Alexander
    You can continue to change this implementation for your needs. For exmaple by sending to the method of the QueryObjectGraph an array of strings (using the params string[] children construct) instead of one string and then in the method implementation to iterate the array and compose the query with multiple Includes. Since query execution will happened in a deffered manner you can do the composition.

    Reply
  3. GuusJuly 24, 2010 ב 19:04

    Hi,

    I implemented your suggestion like so:

    public class EFRepository : IRepository where T : class
    {

    public IEnumerable
    QueryObjectGraph(Expression> filter, params string[] children)
    {
    ObjectQuery query = ObjectSet;

    foreach (var child in children)
    {
    query = query.Include(child);
    }

    return query;
    }

    }

    Works like a charm. Kuddo’s to you!

    Best regards,
    Guus

    Reply
  4. GuusJuly 24, 2010 ב 19:09

    Oops! Forgot the filter:

    not:
    return query;

    but:
    return query.Where(filter);

    Guus

    Reply
  5. Gil FinkJuly 25, 2010 ב 8:37

    @Guus,
    Thanks for sharing.
    Glad I could help :-)

    Reply