.NET Repository Pattern
Implement the repository pattern with Entity Framework Core.
Source code
public interface IRepository<T> where T : class
{
Task<T?> GetByIdAsync(int id);
Task<IReadOnlyList<T>> ListAsync();
Task AddAsync(T entity);
void Remove(T entity);
Task<int> SaveChangesAsync();
}Walkthrough
The repository pattern puts a thin abstraction over data access, so the rest of your app depends on an interface rather than on Entity Framework directly. That keeps your business logic testable and your persistence swappable. Both files are on the left.
1. The contract
A generic IRepository<T> describes what every repository can do, with no EF Core types
leaking out. Your services depend on this — not on DbContext.
public interface IRepository<T> where T : class
{
Task<T?> GetByIdAsync(int id);
Task<IReadOnlyList<T>> ListAsync();
Task AddAsync(T entity);
void Remove(T entity);
Task<int> SaveChangesAsync();
}2. A generic base implementation
Repository<T> resolves the right DbSet<T> from the context, so one class serves every
entity — no per-entity boilerplate.
public Repository(AppDbContext db)
{
_db = db;
_set = db.Set<T>();
}3. Reads
FindAsync hits the change-tracker/identity-map first. For list queries we add
AsNoTracking() because read-only results don't need change tracking — it's faster and
lighter.
public async Task<IReadOnlyList<T>> ListAsync() =>
await _set.AsNoTracking().ToListAsync();Use AsNoTracking() for any query whose results you won't modify and save — it skips
the snapshot EF would otherwise keep for change detection.
4. Writes and the unit of work
AddAsync/Remove stage changes; nothing touches the database until SaveChangesAsync.
Exposing save separately lets a caller batch several operations into one transaction.
public async Task AddAsync(T entity) => await _set.AddAsync(entity);
public void Remove(T entity) => _set.Remove(entity);
public Task<int> SaveChangesAsync() => _db.SaveChangesAsync();Entity-specific repositories can subclass this base to add queries that only make sense for one type. The full files are in the panel.