7

I have seen many repository pattern implementations. Specifically of 2 types

  1. They expose the generic repository which is queryable and expects a lamba expression from service class to get data from database.

  2. Write methods to get the data from database based on business requirements and encapsulate the logic (even lambda) of retrieving the data.

Which one is a better approach?

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
Abhay Naik
  • 410
  • 3
  • 15
  • Are you not confusing lambda's with generics. i.e. IRepository is your interface and ProductRepository : IRepository your implementation. – Andrew Mar 02 '11 at 11:37

2 Answers2

13

I really prefer the second one.

Even I've seen articles from top bloggers on .NET world, queryables, for me, are evil in a repository.

Reasons:

  1. A repository is like a collection of objects but stored wherever its implementation has defined.

  2. A repository abstracts the way data is mapped to object. Data store could be whatever, but business relies on repository in order to retrieve, add, update or remove domain objects.

  3. Any read or write access to the underlying store must be managed by the repository itself - or any other underlying layer -.

Queryable destroys most of these points and/or reasons.

For example, why you would design a GetProductByName, GetProductByCode, if you can do it with LINQ on IQueryable?

And Queryable works bad in n-tier scenarios, since you won't be having access to the database connection in another tier than the one which returned a deferred set.

I don't think "queryable" concept and repository should be good for any software design, because it's telling that repository is useless.

Queryable is like designing a GetAll method. What's the point of a GetAll in a repository? Repository will be retrieving all domain objects and you'll be filtering them in business. But... Wait... Repository isn't supposed to retrieve domain objects with some criteria, is it?

Although I find queryable incompatible with repository, designing and implementing some repository method that accepts a lambda expression or any delegate in order to give some kind of filter or behavior, for me, is fine. This isn't deferred execution, it's delegation.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • Totally agree with You... http://stackoverflow.com/questions/5156775/if-i-expose-iqueryable-from-my-service-layer-wouldnt-the-database-calls-be-less/5156952#5156952 – Arnis Lapsa Mar 02 '11 at 13:32
  • Great one...me also preferred the second one. It just takes more pain designing such repository but it gives right abstraction. Just wanted to know if 2nd approach can have bottle neck... – Abhay Naik Mar 02 '11 at 15:16
  • I doubt the concept of 2nd approach can have a bottle neck. It's a predictable flow. Great to know it's useful for you! – Matías Fidemraizer Mar 02 '11 at 16:06
1

I prefer the first one.

The queryable version is better because it requires less code and is more flexible.

You don't have to know in advance what you are looking for.

  // instead of repository.FindByMinimumAge(18)
  customerList = repository.Find<Customer>(c => c.Age >= 18)

With the second approach your Repository-Interface must contain a Method FindByMinimumAge(int minimumAge) (and a methodFindByName and a method ....)

update

The repository interface looks like this.

public interface IRepository<T> where T : class
{
    IEnumerable<T> Find(Expression<Func<T, bool>> where);
    ...
}

This can be implemented ie by NHibernate, Linq2Sql or "Mock using an arraylist".

k3b
  • 14,517
  • 7
  • 53
  • 85