Что такое Unit of Work и Repository в C#

Unit of Work и Repository — это два паттерна проектирования, которые используются для управления доступом к данным в C#. Они помогают разделить логику работы с базой данных и бизнес-логику, обеспечивая гибкость и удобство.

Паттерн Repository

Repository (репозиторий) — это абстракция, которая скрывает детали работы с базой данных, предоставляя удобный интерфейс для взаимодействия с данными.

Пример реализации Repository

public interface IRepository<T> where T : class
{
    IEnumerable<T> GetAll();
    T GetById(int id);
    void Add(T entity);
    void Update(T entity);
    void Delete(int id);
}

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 IEnumerable<T> GetAll() => _dbSet.ToList();
    public T GetById(int id) => _dbSet.Find(id);
    public void Add(T entity) => _dbSet.Add(entity);
    public void Update(T entity) => _dbSet.Update(entity);
    public void Delete(int id)
    {
        var entity = _dbSet.Find(id);
        if (entity != null) _dbSet.Remove(entity);
    }
}

Паттерн Unit of Work

Unit of Work управляет транзакциями и группирует несколько операций репозитория в один логический блок.

Пример реализации Unit of Work

public interface IUnitOfWork : IDisposable
{
    IRepository<Product> Products { get; }
    void Save();
}

public class UnitOfWork : IUnitOfWork
{
    private readonly AppDbContext _context;
    public IRepository<Product> Products { get; }

    public UnitOfWork(AppDbContext context)
    {
        _context = context;
        Products = new Repository<Product>(context);
    }

    public void Save() => _context.SaveChanges();
    public void Dispose() => _context.Dispose();
}

Использование Unit of Work и Repository

using var unitOfWork = new UnitOfWork(new AppDbContext());
var product = new Product { Name = "Laptop", Price = 1200 };

unitOfWork.Products.Add(product);
unitOfWork.Save();