Domanda

I've struggled with implementing repository and service patterns for a while while using ASP.net MVC and Entity Framework.

I understand the purpose of the repository pattern and how it helps with testing and makes the data layer interchangeable. However, Entity Framework is already a repository/unit of work pattern. Every implementation of the repository pattern that I've seen either strips EF of it's useful features or implements an IQueryable<T> property that makes the purists squirm.

If I'm writing interfaces for my service layer, then implementing concrete versions of those services is there a reason I should not just use Entity Framework as my data layer directly in the service (as opposed to wrapping it in a repository/unit of work pattern and injecting the dependency)? For example: can't I create an IService interface, then create a concrete EfService (Entity Framework) or NhService (NHibernate version) implementations?

I can then use my IoC container to inject the desired service and data contexts.


Here is an example of what I have come up with based on Sergey's comments: https://github.com/sweeperq/Monona

Is that how the pattern is meant to be implemented?

È stato utile?

Soluzione

I always go with repository interfaces.

First reason is testability - DbContext and DbSet<T> are hard to mock. So, unit-testing of services becomes really hard, if even possible.

Second reason is IQueryable<T> being exposed by EF. It makes data-access logic spread over whole application, which violates SRP and makes fixing issues harder.

Third reason might be not very important - ability to switch interface implementations - not only with real object and mock, but with different data-access framework. You always think - "no, I definitely will stick with EF". But in real world I have experience of switching to Dapper due to performance issues and ease of development. And once I had experience of switching from in-memory data storage to EF. So, it's always nice to have that option instead of depending on framework-specific API.

Fourth reason is nice domain-specific API which repositories give you. Instead of having something like db.Orders.Where(o => o.Category == "Food") you have nice method repository.GetOrdersByCategory.

Another reason is that you have data-access logic in one place. No duplication. In sample above you can have five places in your application which use same query to filter orders by category. With repository you will have single method for that, which will be called in five places. Consider what if your business rules will change? E.g. you will need also to check if category is active.

Also keep in mind - once you have UoW and Repository base classes and interfaces, you can reuse them in different projects.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top