Should write complex query in Repository or Service layer?

ε祈祈猫儿з 提交于 2019-11-30 20:51:05

This depends on opinion and the use case, but I personally do not agree with some of the key points you mentioned.

Return IEnumerable instead of IQueryable

Agree. Returning IQueryable defeats basic purpose of existence of Repository. There are lot many articles on net explaining how this creates more problem than a solution. Though, I have learned to never say never. Refer this, this, or this. Or simply search google.

Repository should take responsibilities for CRUD operations only

Agree. With simple CRUD, it may also do complex reads and writes. My experience tell that in exceptional cases, you have to put a part of business logic in repository if you want to implement it on RDBMS side. This is not right or wrong. If you know what you are doing, there should not be an issue.

Return type of repository method should be model (entity)

If you are not using DDD, then yes. Otherwise, it is implementation decision. With full ORM like EF or NHibernate, it is better to return Domain Model directly instead of per table Entity instance.

It is always suggested that Repository should return Domain Model. That way, mapping of data returned from RDBMS with the Domain Model (and vice versa) becomes responsibility of repository. This avoids necessity of leaking the persistence concerns outside the repository and thus makes your rest of the application persistence ignorant.

But, not every application implement DDD. Many small applications design entities those are mapped 1 to 1 with their database design. In this case, repository may return entity (which is equivalent to your table and fields) itself and mapping becomes responsibility of calling code. Or, repository may map the necessary model and return the model itself. This is strongly discouraged because the problems stated above. With this, you have to give up some of the features full ORMs provide.

All this depends on what is your problem, what are your design objectives, size of application and other design patterns implemented etc. That is why it becomes design decision.

Only implement repository for aggregate root

Agreed if it is with DDD. If not, multiple choices are available like per table repository. Again, depends on use case.

About complex query

It is not necessary that repositories should only implement simple CRUD methods. It may also return complex object graph. It may do complex querying. That said, with simple methods like Get, GetById etc, it may also consume complex methods like GetTopBrokenVehicles(vehicleType, top). It is absolutely fine if you write separate method for complex query.

Challenge is that, how you accept the necessary parameters. You may accept the parameters inline or build separate simple input parameter class.

Here is sample code for Repository and UoW.

One of benefit of using Repository Pattern is hiding complex queries, you should see repository as collection of objects in memory (martin fowler):

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers https://martinfowler.com/eaaCatalog/repository.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!