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
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.
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.