Skip to main content

Customize the Repository

In most cases, the default CRUD operations provided by IRepository<TEntity> are sufficient. But when your domain requires richer queries, you need to extend the base contract with domain-specific methods.

This section covers how to design, implement, and register custom repositories that follow the new Kista model — where generic query capabilities are hidden behind protected members of Repository<TEntity, TKey>, and domain-specific queries are exposed through the Specification Pattern.

Overview

The new design model separates concerns clearly:

LayerResponsibility
IRepository<TEntity, TKey>Core CRUD + key look-up + unsorted pagination
Repository<TEntity, TKey>Protected query hatch + ready-made query methods
Your custom interfaceDomain-specific query methods (Specification Pattern)

Topics

TopicDescription
Interface DesignHow to define your custom repository interface following the Specification Pattern
ImplementationHow to extend Repository<TEntity, TKey> and use the protected query hatch
Query MethodsTrade-offs between specific methods and generic page queries
RegistrationHow to register custom repositories with the DI container

Quick Example

// 1. Define the domain interface
public interface IProductRepository : IRepository<Product, Guid> {
Task<Product?> FindByCodeAsync(string code, CancellationToken ct = default);
Task<IReadOnlyList<Product>> FindByNameAsync(string name, CancellationToken ct = default);
}

// 2. Implement using Repository
public class ProductRepository : Repository<Product, Guid>, IProductRepository {
protected override IQueryable<Product> Query() => _context.Set<Product>().AsQueryable();
// ... implementation details ...
}

// 3. Register with DI
builder.Services.AddRepositoryContext()
.UseEntityFramework<AppDbContext>()
.AddRepository<ProductRepository>();