Repository means three different things on Google — Git hosting, a design pattern, and plain English. This page defines repository in software and connects it to .NET and EF Core.
Implementation guide: repository pattern in .NET. Query reuse: specification pattern.
Repository definition (software)
Definition: A repository is a persistence abstraction that presents a collection-like interface for accessing domain objects. Application and domain layers call repository methods; the implementation knows how to map to tables, documents, or APIs.
Application service / MediatR handler
│
▼
IOrderRepository ←── contract (definition lives here)
│
▼
EfOrderRepository (DbContext, LINQ, SQL)
│
▼
SQL Server
Purpose: isolate how data is stored from what the business wants to do.
Define repository in plain English
To define repository without jargon:
A repository is the single door your code uses to get or save records of one kind — orders, patients, products — using named operations instead of ad-hoc queries everywhere.
Analogy: a library catalog desk. You ask for "books by author X published after 2020." The desk (repository) knows the stacks (database). You do not wander the shelves from every room in the building.
Repository meaning in domain-driven design
In DDD, a repository:
- Represents a collection of aggregates (usually one aggregate root per repository)
- Hides persistence mechanics (EF Core, Dapper, Cosmos)
- Returns domain objects or read models, not
DataRow - Enforces consistency boundaries — load an
Orderwith itsLinesas one unit when needed
It is not a generic GetAll() on every table unless your domain truly treats every entity as a flat CRUD row.
Repository vs DbContext in .NET
| Repository (interface) | DbContext (EF Core) | |
|---|---|---|
| Role | Named persistence port | ORM + unit of work |
| Typical methods | GetBoardItemsAsync(filter) | DbSet<Order>, SaveChangesAsync |
| When to add | Reused complex queries, test seams | Always — EF is the implementation |
| Risk | Ceremony wrapper over DbSet | Leaking IQueryable to handlers |
Key insight: DbContext is already a repository and unit of work. DbSet<T> is the collection gateway. Add IOrderRepository when it reduces coordination cost — not by default.
public interface IOrderReadRepository
{
Task<OrderDetailDto?> GetDetailForInvoiceAsync(Guid orderId, CancellationToken ct);
Task<IReadOnlyList<OrderBoardItem>> GetBoardItemsAsync(
OrderBoardFilter filter, CancellationToken ct);
}
That is a repository in the useful sense — business-language methods, one place to tune SQL.
Repository vs DAO vs service
| Pattern | Focus |
|---|---|
| Repository | Collection-like access to aggregates |
| DAO (Data Access Object) | Lower-level CRUD per table — common in Java, less idiomatic in modern .NET |
| Application service | Orchestrates use cases; may call repositories |
| Specification | Composable query objects used inside or instead of fat repositories |
When the repository pattern helps
- Same complex query in three handlers — centralize in
ICaseReadRepository - Testing orchestration — mock
IOrderRepository, notDbSet<Order> - Swappable persistence — rare; usually you still have one EF database
When repository is overkill
IRepository<T>withGetAll,GetById,Deleteon every entity- Pass-through wrappers that only forward to
DbContextwith no named query - Hiding
IQueryableuntil every method isGetByIdWithDetailsAndAlso…
Decision guide: repository pattern useful vs overkill.
If an interviewer asks
"Define repository."
Persistence abstraction presenting a collection interface for an aggregate — hides storage details from domain logic.
"DbContext vs repository?"
DbContext is the EF implementation of unit-of-work + repository. Extra interfaces should encode named queries, not duplicate DbSet.
"Repository vs specification?"
Repository is the port; specification composes query predicates. Use specifications when filters combine; use focused repository methods when the query is stable and named.
Hub: design patterns.