Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository/Unit of Work pattern - How to query a repository for objects meeting certain criteria?

I have a standard repository interface in C# which includes the following methods:

IEnumerable<T> GetAll();
T GetById(int id);
void Delete(T entity);
void Add(T entity);

At my domain layer all I am instantiating is a new Unit of Work wrapper and passing it to a repository. The Unit of Work wrapper class hides whether I'm using NHibernate or Entity Framework and exposes a Commit() method.

In my domain layer, how can I query for objects which meet only a particular criteria?

I think what I'm doing at the moment is terribly inefficient. I am currently doing this:

var results = myRepository.GetAll().Where......

If I have a very large amount of objects, is GetAll() going to return every one of them before filtering out the ones I don't need? How can I prevent unwanted object from being returned at all?

Obviously I could add more methods to the interface, but this doesn't seem in keeping with exposing only CRUD operations via the interface.

i.e. - I don't think I should be adding things like (but maybe I'm wrong):

IList<T> GetAllWhereMeetsMyCriteria();
like image 749
JMc Avatar asked May 14 '11 10:05

JMc


2 Answers

Yes your GetAll().Where will pull all your objects from database to your application and perform linq-to-objects. @Kamyar solution will do the same. @Dysaster has provided a correct solution while I was writing this answer.

First of all - do you really need repository which must support both NHibernate or EF? Is it customer requirement? If not you are wasting resources. Select the technology and create minimal abstraction needed for your application to follow separation of concerns.

If you really need high level abstraction and absolute independence on persistence API you should use the third pattern from the family - Specification pattern. With custom specifications you will be able to change persistence to anything if you translate your conditions described by specification into actions needed on data source. Criteria API in NHibernate or extension methods on IQueryable are specifications but they are technology dependent.

like image 75
Ladislav Mrnka Avatar answered Nov 10 '22 01:11

Ladislav Mrnka


Have a look at the repository pattern used in this blog post [weblogs.asp.net]. I have found the source code to employ a few interesting patterns that I keep returning back to and checking again. The code implements both repository and unit of work patterns.

To answer your specific question, the repository interface contains the method:

IEnumerable<T> GetMany(Expression<Func<T, bool>> where);    

It is implemented as follows in the RepositoryBase<T> class:

public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
    return dbset.Where(where).ToList();
}

Probably both EF and NHibarnate will have the interfaces necessary to support this usage.

like image 35
vhallac Avatar answered Nov 10 '22 00:11

vhallac