As introduced earlier in the design section, the Query Specification pattern is a Domain-Driven Design pattern designed as the place where you can put the definition of a query with optional sorting and paging logic.
The Query Specification pattern defines a query in an object. For example, in order to encapsulate a paged query that searches for some products you can create a PagedProduct specification that takes the necessary input parameters (pageNumber, pageSize, filter, etc.). Then, within any Repository method (usually a List() overload) it would accept an IQuerySpecification and run the expected query based on that specification.
An example of a generic Specification interface is the following code from eShopOnweb.
Then, the implementation of a generic specification base class is the following.
The following specification loads a single basket entity given either the basket’s ID or the ID of the buyer to whom the basket belongs. It will eagerly load the basket’s Items collection.
And finally, you can see below how a generic EF Repository can use such a specification to filter and eager-load data related to a given entity type T.
In addition to encapsulating filtering logic, the specification can specify the shape of the data to be returned, including which properties to populate.
Although we don’t recommend to return IQueryable from a repository, it’s perfectly fine to use them within the repository to build up a set of results. You can see this approach used in the List method above, which uses intermediate IQueryable expressions to build up the query’s list of includes before executing the query with the specification’s criteria on the last line.