Универсальный репозиторий и негерметичная абстракция

Я реализую шаблон хранилища. Мои основные причины для этого:

  • Абстрагирование клиентского кода от особенностей персистентности (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 таблиц