Module 2 of 6
Details of the Repository Pattern
Repository Pattern: Simplifying Data Access
The Repository Pattern creates an abstraction layer between the application and the data source. It centralises data access logic and avoids code duplication.
Generic Interface Example
Here is a simple implementation of a generic repository:
public interface IRepository<T> where T : class
{
Task<T?> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
Task AddAsync(T entity);
void Update(T entity);
void Delete(T entity);
}
Implementation with Entity Framework Core
A repository for a specific entity can derive from this interface:
public class Repository<T> : IRepository<T> where T : class
{
private readonly DbContext _context;
private readonly DbSet<T> _dbSet;
public Repository(DbContext context)
{
_context = context;
_dbSet = context.Set<T>();
}
public async Task<T?> GetByIdAsync(int id) => await _dbSet.FindAsync(id);
public async Task<IEnumerable<T>> GetAllAsync() => await _dbSet.ToListAsync();
public async Task AddAsync(T entity) => await _dbSet.AddAsync(entity);
public void Update(T entity) => _dbSet.Update(entity);
public void Delete(T entity) => _dbSet.Remove(entity);
}
This pattern improves readability and reduces repetitive data access logic in the application.
Check your understanding
In the module's example, what does the GetByIdAsync method do?
Why use an IRepository<T> interface instead of a direct implementation?