I’m using NHibernate for data access, but accessing it through a façade layer. This layer consists of interfaces for the repositories, plus an IUnitOfWork interface which corresponds to the ISession object.
In order that retrieved entities are managed correctly, repositories are passed an IUnitOfWork in their constructor and the IUnitOfWork is used for the loading.
The IUnitOfWork contains a property called All, which retrieves all entities of the class as an IQueryable (for later filtering). Thus, a repository method to retrieve all entities created this year might look like the following:
NB: this is not the complete code for these interfaces and classes! Only the code relevant to my question.
IUnitOfWork interface:
IQueryable<T> GetList<T>();
UnitOfWork concrete class:
public IQueryable<T> GetList<T>()
{
return _session.Linq<T>();
}
IFooRepository interface
IQueryable<Foo> All { get; }
IEnumerable<Foo> ThisYearsFoos{ get; }
FooRepository concrete class
public IQueryable<Foo> All
{
get { return _unitOfWork.GetList<Foo>(); }
}
public IEnumerable<Foo> ThisYearsFoos
{
get { return All.Where(x => x.DateCreated > new DateTime(2010,1,1);}
}
I would like to add functionality to specify fetch strategies so that related entities can be eagerly loaded. So let’s say Foo has a property corresponding to another entity, Bar:
public class Foo
{
public Bar {get;set;}
}
The mapping file specifies that Bar is lazy-loaded, but in my ThisYearsFoos repository property I would like to specify that Bar should be eagerly loaded to avoid N+1 selects.
In Linq to NHibernate we can specify eager fetching using the Expand() extension method. However, this extension method belongs to the NHibernateQueryable type, whereas the IUnitOfWork interface’s GetList method only knows about IQueryable.
Clearly I don’t want the IUnitOfWork interface to know about INHibernateQueryable since it is supposed to not know about NHibernate.
Using the design I have specified above, is there a way to do this that I haven’t been able to think of? Or is my design in need of a rethink?
Thanks
David