We have a complicated query in Entity Framework which filters on the grandchild and selects parent attribute. Our current architecture goes from Data Entity --> Domain --> Dto

Would this kind of query be a Repository Method, Domain Service, or Application Method?

select distinct c.customerName
from dbo.customer customer
inner join dbo.Transactions transaction
    on transaction.customerid = customer.customerid
inner join dbo.Purchases purchases
    on purchases.PurchaseId = transaction.PurchaseId
inner join dbo.Product product 
    on transaction.ProductId = product.ProductId
where tra.BKProduct = @ProductInput

IEnumerable<Customer> result = db.Customer
                                 .Where(p => p.Transactions.SelectMany(c => c.Purchases).Select(gc => gc.Product.Where(gc => gc.BKProduct == ProductInput).Any());

At What Level?

The perennial question.

  • What is the lowest level with reasonable access to all that information?
  • What is the highest level where such an implementation isn't too detailed?

Generally that would be the repository as it stores all that information, and is usually defined in terms of relational logic. So it should fit right in. Personally that is where I would place it.

However, the repository isn't necessarily the best fit. If for example this application provides users with the ability to specify queries for reporting, then relational logic is also apart of the domain. In such a case it may be more reasonable to place this knowledge inside the domain layer for easier articulation.

Shearing Layers

Another way to look at this is to observe the shearing forces in the application. Ideally you want code that is subjected to the same shearing force to be in the same location.

For example the particular data mapping frame work you are using will eventually be decommissioned, or receive a breaking change. In either case you will have to change/review all code associated with the framework.

If that code is consolidated in a single cohesive block, it is trivial to find, and update, or replace.

If it is peppered throughout the code base... ... ... The brochure saying it will be fun isn't accurate.

The same goes for every library/framework/language/operating system used or targeted by your code. Some of these things are in constant flux (looking at those frameworks) while others are so long lived (C) that they are practically guaranteed to exist.

Applying this to your query. If you chose to implement this using the data mapping framework directly then it definitely lives with all of the other code dealing with the same details. This will probably be the repository.

If you choose to use the language based implementation (LINQ). It probably shouldn't live inside the repository simple because its implementation details aren't in common - it has a different shearing force. A better place for it to live would be within the domain service/application method, depending on other concerns like security and access to data.

  • yeah, I was guessing Domain Level; Repository is more for Simple CRUD, Read, Insert Delete; this query seems lot more complicated – user370878 Jul 27 '20 at 15:38
  • you mentioned "domain service/application method, depending on other concerns like security and access to data.", however domain and application service are two different things, seems like we got all 3 answers here : ) – user370878 Jul 27 '20 at 15:55
  • Because there is an amount of nuance here. Its not like it must live in a specific place. The question is more about what makes life better, and that's qualitative not quantitative. Domain knowledge should be in the domain layer, but sometimes these queries pop up in presentation services to adapt the backend-services for consumption by some client. These presentation services do not always have a distinct domain layer, as they are for the most part proxies. So yes i'm hesitating to say, this and always this. There is always a But. – Kain0_0 Jul 29 '20 at 0:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy