Domain-Driven Design
Repositories
Finding aggregate roots in the model’s terms without exposing tables.
A repository gives the application access to aggregate roots in the model’s terms. Its interface belongs beside that model. SQL, Entity Framework, and document-store details belong behind it.
Ask for an aggregate
Microsoft’s eShop puts the repository contract next to the Order aggregate:
public interface IOrderRepository : IRepository<Order>
{
Order Add(Order order);
void Update(Order order);
Task<Order> GetAsync(int orderId);
}
The application asks for an Order by order id and receives the aggregate root. The contract does not expose an Orders table or let the caller update one child row around the root. eShop’s Entity Framework implementation lives in its Infrastructure project.
This is the collection metaphor in practice. The repository speaks about adding, finding, and updating Orders. It does not promise that an aggregate is stored in one table.
A DbSet is the table leaking
Here is a contrasting example from an application that exposes its campaign table directly:
public interface IAppDbContext
{
DbSet<Campaign> Campaigns { get; set; }
}
Every caller can now compose an Entity Framework query, include arbitrary rows, and update properties without expressing the aggregate it meant to load. The application depends on the shape and abilities of the store.
A class named repository does not automatically fix this. The contract must return aggregate roots and preserve their boundary. A port that replaces hourly delivery rows is a measurement store, even if its type ends in Repository.
Not every store is a repository
MiniVerine does not yet contain aggregate repositories. Its PersistencePlan specifies future ports for inbox, outbox, dead letter, and saga storage. Those are message and process stores with their own semantics.
Calling an inbox an Envelope repository would hide behaviour such as claiming work, deduplicating delivery, and moving a failed message to dead letter. Repository is not the polite name for every database interface.
When something happens inside the aggregate you did load, the rest of this model may need to hear it in the domain’s words. That is Domain Events.