DCSIMG
Eager Loading with Repository Pattern and Entity Framework - Gil Fink's Blog

Gil Fink's Blog

Fink about IT

News

Microsoft MVP

My Facebook Profile My Twitter Profile My Linkedin Profile

Locations of visitors to this page

Creative Commons License

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2013 Gil Fink

Hebrew Articles

Index Pages

My OSS Projects

English Articles

Eager Loading with Repository Pattern and Entity Framework

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.

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# June 22, 2010 9:15 AM

The Morning Brew - Chris Alcock » The Morning Brew #626 said:

Pingback from  The Morning Brew - Chris Alcock  &raquo; The Morning Brew #626

# June 22, 2010 10:35 AM

James Alexander said:

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?

# June 22, 2010 4:48 PM

Eager Loading with Repository Pattern and Entity Framework – Gil … | Programming Blog Imagik.org said:

Pingback from  Eager Loading with Repository Pattern and Entity Framework &#8211; Gil &#8230; | Programming Blog Imagik.org

# June 23, 2010 3:35 AM

Twitter Trackbacks for Eager Loading with Repository Pattern and Entity Framework - Gil Fink on .Net [microsoft.co.il] on Topsy.com said:

Pingback from  Twitter Trackbacks for                 Eager Loading with Repository Pattern and Entity Framework - Gil Fink on .Net         [microsoft.co.il]        on Topsy.com

# June 23, 2010 5:39 AM

Gil Fink said:

@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.

# June 24, 2010 8:13 AM

Guus said:

Hi,

I implemented your suggestion like so:

   public class EFRepository<T> : IRepository<T> where T : class

   {

...

       public IEnumerable<T> QueryObjectGraph(Expression<Func<T, bool>> filter, params string[] children)

       {

           ObjectQuery<T> query = ObjectSet;

           foreach (var child in children)

           {

               query = query.Include(child);

           }

           return query;

       }

...

}

Works like a charm. Kuddo's to you!

Best regards,

Guus

# July 24, 2010 7:04 PM

Guus said:

Oops! Forgot the filter:

not:

return query;

but:

return query.Where(filter);

Guus

# July 24, 2010 7:09 PM

Gil Fink said:

@Guus,

Thanks for sharing.

Glad I could help :-)

# July 25, 2010 8:37 AM