Помогите разобраться с паттерном Репозиторий

В своем пет-проекте не могу понять как лучше поступить с репоизторием. Проект состоит из нескольких микросервисов, каждый в свою очередь использует универсальный дженерик репозиторий:

public class Repository<TEntity, TKey> : IEFRepository<TEntity, TKey> 
    where TEntity : class where TKey : notnull

Понимаю что нарушаю принципы чистой архитектуры, т.к. детали специфичные для EFCore "вспплывают" на уровень бизнес-логики. Например в IEFRepository<TEntity, TKey> есть такой метод:

 public async Task<TEntity?> GetFirstOrDefaultAsync(
    Expression<Func<TEntity, bool>>? filter = null,
    Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>>? include = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>? orderBy = null,
    bool asNoTraсking = true,
    CancellationToken ct = default)

Отсюда планирую создать отдельные доменные интерфейсы для каждого микросервиса по типу IUserRepository и свою реализацию, при чем, при создании конретного репозитория хочу просто отнаследоваться от своего общего дженерик репозитория (именно от класса), чтобы работать внутри с его методами, а во вне пойдут методы из доменного интерфейса. Такой подход адекватен? Или наследование от общего репозитория это лишнее?

И дополнительный вопрос, насчет того как лучше работать с отслеживанием сущностей? создавать отдельные методы с трэкингом по типу:

Task<User?> GetByIdWithTrackingAsync(Guid id, CancellationToken ct);

или

Task<User?> GetByIdForUpdateAsync(Guid id, CancellationToken ct);

Затем соответсвенно изменять сущность и вызывать Update() или SaveChanges()?

Также можно всегда возвращать сущности без отслеживания и апдейтить их через ExecuteUpdateAsync(), но не уверен, что такой подход корректен. С другой стороны работа с отслеживаемыми сущностями это особенность именно EFCore, если я, например, захочу перейти на Dapper, то там уже все будет иначе.


Ответы (0 шт):