Я пытаюсь понять, как правильно реализовать шаблон UoW и Repository с Entity Framework. Я видел много постов против этого, но это все еще кажется правильным путем.
Я пытаюсь сделать это по этому Сообщение блога. Последнее, что я пытаюсь понять, - это как внедрить репозитории в UoW, но таким способом, который позволяет мне делать это по требованию. Количество репозиториев может вырасти, как и конструктор. Более того, создание экземпляров всех репозиториев для операции, которая может потребовать только 1 или 2, кажется пустой тратой ресурсов.
Как мне это сделать, чтобы я мог довольно легко писать модульные тесты?
Единственный способ, которым я обнаружил, который позволяет мне вводить репозитории НЕ в конструктор (так что не все они создаются, даже если они не нужны для конкретной операции), - это делать это в геттере:
private IGenericRepository<Blog> _blogRepository;
private IGenericRepository<Post> _postRepository;
public UnitOfWork(BloggingContext bloggingContext)
{
_bloggingContext = bloggingContext;
}
public IGenericRepository<Blog> BlogRepository
{
get
{
return _blogRepository = _blogRepository ?? new GenericRepository<Blog>(_bloggingContext);
}
}
Однако такой подход создает много шума в коде, потому что, когда у меня будет 50 репозиториев, мне понадобится 50 реквизитов.
@Sentinel Я хотел создать стандартный шаблон UoW + Repository, а не набор UoW. Все репозитории в одном UoW должны совместно использовать DbContext. Вторая часть о методе Т. - отличное предложение. Я нашел этот stackoverflow.com/questions/16064902/…, и он похож на то, что вы предложили с помощью dict.
они также упоминают Lazy <T>, который может вам помочь.
@Sentinel Ну, моя последняя проблема заключается в том, что с подходом dict мне пришлось бы делать некрасивое приведение при каждом использовании: / Есть предложения? редактировать. Я мог бы использовать фабрику в UoW, чтобы получить все репозитории по запросу. Это должно хорошо работать?
@ catdoanyrhing33 Не уверен, почему вам нужно использовать приведение везде, просто верните T в общем методе get <T>. Итак, у вас будет var X = get <myrepo> (); с макушки, которая не требует гипсовой повязки, верно?
обход фабрик тоже работает. Ленивый экземпляр, принимающий универсальный параметр, можно рассматривать как тип фабрики.
У меня ограниченный опыт работы с контейнерами IoC. По какой-то причине большинство проектов, над которыми я работал, их избегали. IMO IoC иногда делает код менее читаемым. Я думаю, что если у вас есть достаточно веские основания для перехода в какую-то заводскую или заводскую конфигурацию, продолжайте. Иногда беспокойство об антипаттернах может быть контрпродуктивным.
Суть фабрики в том, что вы можете указать, какой тип репо использовать, например EF, in-memory или другие реализации backend dataaccezs. Вообще это перебор. БД, как правило, никогда не меняются, что означает, что вы не собираетесь переключаться с EF на Azure NoSQL и не хотите программировать для этого сценария.
Молодцы с реализацией.





Возможно, вы захотите объединить описанный подход (который мне нравится) с общим подходом к репозиторию, описанным здесь https://cpratt.co/truly-generic-repository/ При правильной реализации шаблона UoW из сообщения в блоге, на которое вы ссылаетесь, вам не понадобится ничего, кроме IReadOnlyRepository из статьи - он предоставит все, что вам нужно для репозитория.
Мне кажется, что вы хотите достичь не UoW, а набора UoW, реализованных в одном классе, в зависимости от данной операции. Сначала я хотел бы спросить, почему вы хотите это сделать. После этого, да, вы можете просто использовать ленивое построение, создав востребованное репо. Если вы хотите избежать большого количества реквизитов, используйте общий метод типа T и сохраните репозитории в словаре или cncurrent словаре, индексированном T