Ответ
Паттерн Репозиторий — это слой абстракции между бизнес-логикой приложения и источником данных (БД, внешний API, файловая система). Его основная цель — инкапсулировать всю логику доступа к данным, делая бизнес-слой независимым от деталей инфраструктуры.
Основные цели и преимущества:
- Единая точка доступа: Все запросы к сущности
Userпроходят черезIUserRepository. - Сокрытие сложности: Бизнес-код не знает, используется ли Entity Framework, Dapper или прямой SQL.
- Упрощение тестирования: Репозиторий легко подменить mock-объектом для модульного тестирования бизнес-логики.
- Централизация правил: Сложные запросы (например, с фильтрацией и пагинацией) не размазываются по коду.
Пример реализации с Generic Repository и спецификациями:
// 1. Базовый интерфейс репозитория
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);
Task<IEnumerable<T>> FindAsync(ISpecification<T> spec); // Для сложных запросов
}
// 2. Конкретная реализация для Entity Framework Core
public class EfRepository<T> : IRepository<T> where T : class
{
private readonly AppDbContext _context;
public EfRepository(AppDbContext context) => _context = context;
public async Task<T?> GetByIdAsync(int id) => await _context.Set<T>().FindAsync(id);
public async Task AddAsync(T entity) => await _context.Set<T>().AddAsync(entity);
// ... остальные методы
}
// 3. Использование в сервисе
public class UserService
{
private readonly IRepository<User> _userRepo;
public UserService(IRepository<User> userRepo) => _userRepo = userRepo; // Внедрение зависимости
public async Task<User?> GetActiveUserByEmail(string email)
{
// Бизнес-логика изолирована от деталей запроса
var spec = new ActiveUserByEmailSpecification(email);
return (await _userRepo.FindAsync(spec)).FirstOrDefault();
}
}
Важно: В современных приложениях на EF Core часто обходятся без "классического" репозитория, используя DbSet напрямую в сервисах, но инкапсулируя сложные запросы в спецификации (Specification pattern) или запросы (Query objects) для сохранения преимуществ тестируемости и управляемости.