One question that I 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.
Gil Fink is a web development expert and ASP.Net/IIS Microsoft MVP. He is the founder and owner of sparXys. He is currently consulting for various enterprises and companies, where he helps to develop Web and RIA-based solutions. He conducts lectures and workshops for individuals and enterprises who want to specialize in infrastructure and web development. He is also co-author of several Microsoft Official Courses (MOCs) and training kits, co-author of "Pro Single Page Application Development" book (Apress) and the founder of Front-End.IL Meetup. You can read his publications at his website: http://www.gilfink.net