The repository pattern abstracts data access behind interfaces—controllers depend on IProductRepository, not raw DbContext. Teams debate its necessity with EF Core; it helps large codebases and testing boundaries.
When it helps
- Centralize complex queries in one place
- Swap EF for another store in tests or migrations
- Keep controllers thin and domain-focused
public interface IProductRepository {
Task<Product?> GetByIdAsync(int id);
Task AddAsync(Product product);
}
public class ProductRepository : IProductRepository {
private readonly AppDbContext _db;
public ProductRepository(AppDbContext db) => _db = db;
// implement with _db.Products...
}
When to skip
Small apps may inject DbContext directly—avoid pointless pass-through repositories that only wrap DbSet with no added logic.
Important interview questions and answers
- Q: Repository vs DbContext directly?
A: DbContext is already a unit-of-work/repository abstraction—extra layer adds value only with real query encapsulation. - Q: Generic IRepository<T>?
A: Convenient but leaky—domain-specific methods (GetActiveProducts) express intent better.
Self-check
- What does a repository hide from controllers?
- When is a repository just unnecessary indirection?