Универсальный репозиторий и негерметичная абстракция
Я реализую шаблон хранилища. Мои основные причины для этого:
- Абстрагирование клиентского кода от особенностей персистентности (Entity Framework)
- Для поддержки тестируемости
Общий репозиторий или нет?
Проблема, с которой я столкнулся, заключается в том, должен ли я иметь общий репозиторий или нет. IQueryable<T> Query()
Метод предоставит вызывающему коду средства для построения определенных запросов. Проблема здесь в том, что это утечка абстракции - специфика Entity Framework теперь просачивается в мой клиентский код.
Как это повлияет на юнит-тестирование? Смогу ли я по-прежнему
ICustomerRepository
с этой реализацией?Как этот эффект разрушает мой слой постоянства? Как таблицы хранения Azure или NHibernate.
В противном случае мне пришлось бы реализовать очень специфический метод запроса на ICustomerRepository
, такие как GetIsActiveByFirstName()
а также GetIsActiveByDistrict()
, Мне это очень не нравится, так как мои классы репозитория будут забиты разными методами запросов. Эта система имеет сотни моделей, и поэтому могут быть написаны и поддержаны сотни или даже тысячи этих методов.
1 ответ
Вы можете иметь относительно чистый IRepository<T>
придерживаясь шаблона.
Доступ к данным LAyer
- ссылка на проект EF и Core
- имеет
Respository<T> : IRepository<T>
- Опция имеет объявление IEFJunk (только если используется несколько репозиториев)
- Ссылка на ядро
- Respository внедряется с Context (обычно во время создания экземпляра)
ядро
- Интерфейсы, которые могут быть "введены"
- IRepository декларация. Без использования типа данных EF.
- Нет ссылки на EF
Так что теперь код в Core вы можете обратиться к IRepository<t>
, Реализующий класс может иметь специфику EF. Но это не может быть доступно из ядра!
так что вы можете иметь IQueryable.
public interface IRepositoryBase<TPoco>{
IQueryable<TPoco> GetListQ(Expression<Func<TPoco, bool>> predicate);
//...
Но если вы решили, что хотите добавить
//...
// logically exposing IQueryable<T> Include<T>(this IQueryable<T> source, string path) from EF
IQueryable<TPoco> IncludeNAVProp(string navToInclude);
}
Затем репозиторий реализации
return Context.Set<TPoco>().Include(navToInclude);
требует, чтобы основным поставщиком был EF. Так что теперь насмешка против фактического поставщика EF.
И если вы не осторожны, EF конкретный код. Утечки из. Действительно, интерфейс IRepository, который имеет КОНЦЕПЦИЮ "включить", уже может считаться УТЕЧКИМ. Сохранение специфики EF в ваших интерфейсах является ключом к предотвращению утечек.
И вы можете иметь 1 IRepository<t>
и 1 Respository<t>
и поддерживать 100 таблиц