Repository

An intermediary between the domain and storage, exposing illusory in-memory collections.

Context

You want to work with your domain as if they were collections, without knowing if SQL, NoSQL, or an API is behind the scenes.

Problem
  • Mixing business logic with SQL contaminates the domain.
  • Changing persistence requires modifying the domain.
Solution

An IXxxRepository interface with Add, GetById, Find that hides persistence.

#Example in C#

public interface IOrderRepository
{
    Task<Order?> GetAsync(Guid id);
    Task<IReadOnlyList<Order>> FindByCustomerAsync(Guid customerId);
    void Add(Order order);
    void Remove(Order order);
}

public class EfOrderRepository : IOrderRepository
{
    private readonly AppDbContext _db;
    public EfOrderRepository(AppDbContext db) => _db = db;

    public Task<Order?> GetAsync(Guid id) => _db.Orders.FindAsync(id).AsTask();
    public Task<IReadOnlyList<Order>> FindByCustomerAsync(Guid customerId) =>
        _db.Orders.Where(o => o.CustomerId == customerId).ToListAsync()
            .ContinueWith(t => (IReadOnlyList<Order>)t.Result);
    public void Add(Order o) => _db.Orders.Add(o);
    public void Remove(Order o) => _db.Orders.Remove(o);
}
When NOT to use it
  • With EF Core, you already have a repository (DbSet<T>). Encapsulating it adds noise unless the domain contract is narrower (read models, specific queries).
  • For simple reads → consider CQRS with direct queries.
Tradeoffs
Pro Con
Isolates the domain from the ORM A thin layer that often just delegates
Tests with fake repositories Risk of exposing LINQ and EF filtering to the domain

#extra #ddd #persistence