It seems that every example I find of the repository pattern, the implementation is different in some way. The following are the two examples I mainly find.
interface IProductRepository
{
IQueryable<Product> FindAll();
}
There is then usually another layer which talks to the repository and calls the FindAll() method and performs any operations such as finding products beginning with the letter 's' or fetching products in a particular category.
The other example I find a lot put all of the find methods into the repository
interface IProductRepository
{
IEnumerable<Product> GetProductsInCategory(int categoryId);
IEnumerable<Product> GetProductsStartingWith(string letter);
IEnumerable<PromoCode> GetProductPromoCodes(int productId);
}
Which path do you recommend I take? Or what are the advantages/disadvantages from each other?
From my understanding having read http://martinfowler.com/eaaCatalog/repository.html the first approach seems to best reflect this?
The Repository pattern. Repositories are classes or components that encapsulate the logic required to access data sources. They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer.
The Repository Design Pattern in C# Mediates between the domain and the data mapping layers using a collection-like interface for accessing the domain objects. In other words, we can say that a Repository Design Pattern acts as a middle layer between the rest of the application and the data access logic.
The repository pattern is intended to create an abstraction layer between the data access layer and the business logic layer of an application. It is a data access pattern that prompts a more loosely coupled approach to data access.
The first one is horrible. IQueryable
is like a GOD object. It's really hard to find a 100% complete implementation of it (even among all OR/Ms). You can expose your ORM directly instead of using it since you'll probably get a leaky abstraction layer otherwise.
Joel says it best (text is from the wikipedia article):
In Spolsky's article, he calls attention to many examples of abstractions that work most of the time, but where a detail of the underlying complexity cannot be ignored, and thus drives complexity into the software that was supposed to be simplified by the abstraction itself
Joels blog entry
The second approach is much easier to implement and to keep the abstraction intact.
Update
Your repository is violating Single Responsibility Principle since it got two reasons to change. The first is if the Products API is changed and the other is if the PromoCode API is changed. You should imho use two different repositories like:
interface IProductRepository
{
IEnumerable<Product> FindForCategory(int categoryId);
IEnumerable<Product> FindAllStartingWith(string letter);
}
interface IPromoCodeRepository
{
IEnumerable<PromoCode> FindForProduct(int productId);
}
Changed things:
Find
when several items are returned and Get
if a single item is returned.Small well defined interfaces makes it easier to spot violations of the SOLID principles since classes the break the principles tend to get bloated constructors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With