Organizationally, where should I put common queries when using Entity Framework Code First?
I'm laying out a new data layer using EF 4.1 Code First, migrating from an older homebrew data layer.
I have set up two assemblies, one for my context and one for all the POCO code first classes.
I have some business logic, for instance, a query against one table (or a few tables) that is used in several different places. Where should I put it?
It can't go in a POCO class because it joins a couple tables and so needs a context. It could go in the context, but that context w开发者_JS百科ould become bloated with hundreds of disorganized queries. Is there a common pattern or arrangement for all the business logic?
Looks like the repository pattern is solution for everything ... Repository is not a silver bullet!
I'm using the repository pattern with EF everyday because when I started my current project several months ago it looked like recommended solution. My conclusions:
- Repository makes interaction with EF much harder. Just browse questions related to EF tags and you will see what complexities must be handled directly on the context, changetracker, etc.
- Generic repository is something that works for CRUD operations but not for real DDD scenarios. Once your repository works with aggregate roots (DDD) generic approach fails.
- Unit testing doesn't work at all because general idea that you will mock repository and test your upper layer without dependencies to EF and database fails once you expose
IQueryable
. Linq-to-entities is only subset of Linq-to-objects and mock doesn't handle referential integrity so many times I saw green unit tests and runtime exceptions. The correct testing approach with EF are integration tests. Mocking repository is only for testing real business logic not related to data access. If you don't have integration test for your business method accessing or persisting data you didn't test it. - Exposing specialized methods like GetByXXX is just step back. Most of these methods are used only once. You will end with the code similar to repositories used for wrapping stored procedures calls. Many developers like ORM just because they can avoid such rigid architecture.
EF itself already offers repository pattern - DbSet
and ObjectSet
are repositories and DbContext
and ObjectContext
are Unit of works. So in my opinion repository pattern is overused. It can be useful in large projects where you need strict layering or in case of placing additional logic to its methods. Using repository just because you want to wrap access to EF is often valueless code and just additional layer of complexity.
You can in the same way create reusable methods defining your queries.
I would use the Repository Pattern. Here is an example using EF code first and MVC Entity Framework 4 CTP 4 / CTP 5 Generic Repository Pattern and Unit Testable
Here are some good reads on the pattern:
- http://www.martinfowler.com/eaaCatalog/repository.html
- http://msdn.microsoft.com/en-us/library/ff649690.aspx
- http://www.devx.com/dotnet/Article/33695/0/page/5
It may also be a good idea to look into Domain Driven Design (DDD) since you are starting with a Domain Model.
Some good reads on DDD:
- http://www.infoq.com/minibooks/domain-driven-design-quickly
- http://lostechies.com/jimmybogard/category/domain-driven-design/
If you use EF directly in business methods (Domain Layer Services & Application Layer Services) then you are not isolating the Domain Model Layer from the infrastructure technologies (EF in this case). That is one of the DDD principles. you should probably have one Repository per Aggregate.
For more info about DDD, see:
Eric Evans' book: http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
Microsoft: http://msdn.microsoft.com/es-es/architecture/en
精彩评论