Specification pattern
Encapsulate filters, ordering, and projections in reusable specification classes.
Cosmos Repository ships with a specification pattern — inspired by ardalis/Specification — that lets you declare a query as a class and run it via IRepository<T>.QueryAsync(spec).
The base types live in Microsoft.Azure.CosmosRepository.Specification:
BaseSpecification<TItem>— abstract base; build aQueryto add filters, ordering, and projections.DefaultSpecification<TItem>— concrete subclass for ad-hoc inline use.PageNumberPageSizeSpecification<TItem>— pre-wired for page-number paging.ContinuationTokenSpecification<TItem>— pre-wired for continuation-token paging.
Simple specification
The specification below queries for all products in a category, ordered by price.
public class ProductSpecificationExamples{ private class ProductsPriceLowestToHighestInCategory : DefaultSpecification<Product> { public ProductsPriceLowestToHighestInCategory(string categoryId) => Query .Where(x => x.PartitionKey == categoryId) .OrderBy(x => x.Price); }
public async Task<IQueryResult<Product>> RunDemoAsync(IRepository<Product> repository) { IQueryResult<Product> orderedProducts = await repository .QueryAsync(new ProductsPriceLowestToHighestInCategory("Clothing"));
return orderedProducts; }}Multiple ordering clauses
Stack OrderBy / OrderByDescending with ThenBy / ThenByDescending to sort by additional properties:
public class ProductSpecificationAdvancedOrderingExamples{ private class ProductsPriceLowestToHighestThenByName : DefaultSpecification<Product> { public ProductsPriceLowestToHighestThenByName() => Query .OrderBy(x => x.Price) .ThenByDescending(x => x.Name); }
public async Task<IQueryResult<Product>> RunDemoAsync(IRepository<Product> repository) { IQueryResult<Product> orderedProducts = await repository .QueryAsync(new ProductsPriceLowestToHighestThenByName());
return orderedProducts; }}Built-in paging specifications
PageNumberPageSizeSpecification<TItem>acceptspageNumber,pageSize, and an optionalreturnTotalflag for total counts.ContinuationTokenSpecification<TItem>acceptspageSizeand acontinuationTokenfor stable, cost-effective scrolling.
Subclass either when your specification needs paging out of the box.
Where to look in the codebase
Real specifications used in the project’s tests and the Specification sample are great references:
BaseSpecification<TItem>— see whatQueryexposes.DefaultSpecification<TItem>— minimal concrete subclass.IQueryResult<TItem>/IPageQueryResult<TItem>— what’s returned.