Repository design pattern
I have seen many repository pattern implementations. Specifically of 2 types
They expose the generic repository which is queryable and expects a lamba expression from service class to get data from database.
Write methods to get the data from databas开发者_运维知识库e based on business requirements and encapsulate the logic (even lambda) of retrieving the data.
Which one is a better approach?
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:
A repository is like a collection of objects but stored wherever its implementation has defined.
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.
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.
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".
精彩评论