2

What is the difference between Query Object and Repository? Martin Fowler 'Patterns of Enterprise Architecture': “an object that represents a database query.”,

Also should a QueryObject always be IQueryable? I heard Repositories should Never be IQueryable.

https://weblogs.asp.net/dotnetstories/repository-iqueryable

  • 1
    Repository can be IQueryable. Problem with IQueryable is if you are using Entity Framework, then you cannot use all LINQ methods with it, because EF don't support all of them. So you kind of leaking database implementation details to the domain logic. – Fabio Aug 22 '18 at 5:55
  • Can you explain what you mean by Query Object and by Repository? While they might be commonly understood terms, I want to know what your definition and usage is. – Euphoric Aug 22 '18 at 5:58
  • Martin Fowler 'Patterns of Enterprise Architecture': “an object that represents a database query.”, feel free to vote up, not sure why it was voted down, just started using stackoverflow last week, – CarSpeed87 Aug 22 '18 at 6:01
  • 2
    While I do think the question is valid, the question body is a bit meagre. Suggestions for improvement: example code, adding your opinion/interpretation, things you prioritize (e.g. are you trying to maximize testability, or minimize development time?), ... As it currently stands, you're essentially asking for feedback on a blog post. Your question also talks about repositories being iqueryable, whereas your linked resource talks about repositories returning iqueryables. That's not the same thing. – Flater Aug 22 '18 at 7:35
  • I see that you are new here. One thing that distinguishes Q&A's from other forums is that we expect a clear problem statement. "I head repositories should never be IQueryable" is not a clear problem statement. Can you provide some additional clarification please? – Robert Harvey Aug 22 '18 at 15:13
5

Your question talks about repositories being IQueryable (i.e. classes implementing the IQueryable interface), whereas your linked resource talks about repositories returning IQueryable objects. That's not the same thing.

For the purpose of this answer, I'm going to assume you misspoke and meant to focus on repositories returning IQueryable objects.


What is the difference between Query Object and Repository?

A query object is essentially a "one method repository". The syntax is slightly different but every query object is intended to effectively mirror what otherwise would have been a repository method. I see little benefit to query objects unless you have a high need for very loose coupling and many multi-entity queries that are unique for a particular use case.


I heard Repositories should never be IQueryable

There are pro/con considerations here. However, while I was initially on the con side (allowing repositories to leak/be IQueryables), I've changed position on that after I've seen the consequences of doing so.

There is a direct advantage to leaking IQueryables from your repositorues: you need to write less boilerplated methods in the repository. For small (personal) projects, I leak IQueryables (and sometimes even skip the repository layer altogether) to minimize the development effort required, I don't want to spend my time writing several "get data" methods that all work slightly differently.

But this is where the antipattern argument enters the fray. When you add a layer, you're doing so with the intention of separating two things. In this case, the repository separates the data storage from the business logic.

When you leak IQueryables from your repository, you are effectively allowing the business logic to directly control the data storage, which means they're not disconnected from one another, which means that the purpose of the repository layer (separating the business logic from the data store) has been undone.

There are also other issues with doing this:

  • Testability is hindered. It becomes much harder to properly mock your repositories when you're testing your business logic.
  • When debugging an issue in the data store logic, you must inherently also look at the business logic in order to figure out which data is being fetched.
  • A developer who only works on the business logic and nothing else, is somehow still required to know which underlying data store is being used.
    • For example, when using LINQ and Entity Framework, EF cannot handle every valid LINQ code. There are some things that simply do not translate to SQL and therefore EF cannot handle them.
    • Therefore, your business logic developer is required to know that EF is being used, which defeats the purpose of having uncoupled the business logic from the data store.

In personal or small scale projects, this isn't as much of an issue. But in enterprise-grade solutions, things such as testability and separation of concerns matter a great deal.

To summarize
The detriments from leaking IQueryables violate several professional coding standards. However, when coding standards aren't high on the priority list, or the code is not used in a professional capacity, leaking IQueryables can minimize development time needed.

  • @MarkThomas: A query object is essentially a "one method repository". The syntax is slightly different but every query object is intended to effectively mirror what otherwise would have been a repository method. I see little benefit to query objects unless you have a high need for very loose coupling and many multi-entity queries that are unique for a particular use case. – Flater Aug 22 '18 at 12:58
  • Your question talks about repositories being IQqueryable, whereas your linked resource talks about repositories returning IQueryables -- That's a distinction without a difference. By definition, methods in a repository that are IQueryable are going to return objects that conform to the IQueryable interface. – Robert Harvey Aug 22 '18 at 15:13
  • @RobertHarvey: A repository which is an IQueryable is effectively public class FooRepository : IQueryable<Foo> { /*...*/ }, which is very different from a repository that returns an IQueryable, i.e. public class FooRepository { public IQueryable<Foo> Get() { /*...*/ } } – Flater Aug 22 '18 at 15:16
  • Yes, I see what you're saying. In practice, very few people write their own IQueryable providers; they rely on the extension methods in Linq or Linq to Entities to return IQueryable collections from their repository methods. – Robert Harvey Aug 22 '18 at 15:25
  • "... every query object is intended to effectively mirror what otherwise would have been a repository method" - This is not true. A "query" object is an object oriented abstraction of a database query. A repository is an abstraction of data persistence. Though the two ideas are related, they are not the same. – Greg Burghardt Aug 22 '18 at 16:24

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.