Доля DbContext в репозиториях в веб-приложении MVC

Вопрос

Каков правильный способ совместного использования EF DbContext в нескольких хранилищах в веб-приложении MVC? Это разумно/необходимо сделать так, каковы подводные камни, делающие или не делающие это?

Фон

Предположим:

  • App.MvcSite (несколько десятков контроллеров, несколько областей и т.д.)
  • App.Services (уровень сервиса, множество сервисов)
  • App.Data​​strong > (много репозиториев и т.д.)
  • ... и т.д. исключены для простоты (первый код EF)

Исследование до даты

Кажется, я нахожу по крайней мере две/три школы мысли на SO и межсетевых экранах.

  • Поделите/внесите свой DbContext в запрос, чтобы один запрос имел один DbContext, общий для всех репозиториев.
  • Совместное использование/область вашего DbContext на уровне службы. Служба поддерживает один DbContext и передает его в каждый репозиторий по мере необходимости.
  • Не разделяйте DbContext, так как они дешевы, чтобы каждый репо имел свои собственные.

На небольшом веб-сайте это не проблема, поэтому большинство примеров MS и сообщества просто не учитывают этого.

В моем опыте до сих пор я не использовал конечные репозитории. У меня всегда были сервисы, использующие DbContext и напрямую меняющие его, поэтому мне не нужно было об этом беспокоиться. Я сказал, что есть большая польза для конечных репозиториев с точки зрения единичного тестирования... мы увидим, сделает ли это все это стоящим.

Мои мысли

(1) Поделитесь/укажите свой DbContext в запросе

Это интересно, так как он ловко избегает ловушки одноэлементного контекста, который, по мнению некоторых разработчиков, является ответом, но найти DbContext не работает. Но, похоже, у него недостаток в том, что он предполагает, что все репозитории, службы и т.д. Будут координироваться по всему запросу... это часто бывает не так, верно? Что делать, если изменения сохраняются одним репо перед другим, завершает свою работу. (Наружный (внутренний (внутренний)))

(2) Поделиться/расширить свой DbContext на уровне службы

Это имеет для меня больше смысла, потому что каждая служба должна координировать конкретную единицу работы (преднамеренный случай). Поэтому, если несколько сервисов были использованы в одном запросе, было бы правильным (если не требуется), чтобы каждый из них имел свой собственный контекст в базе данных.

(3) Не используйте DbContext, так как они дешевы

Так я всегда это делал... ну, на самом деле у меня почти всегда был только один DbContext для запроса, потому что вызывалась только одна служба. Иногда это может быть два, потому что два оператора были вызваны контроллером, который координировал работу. Но, учитывая мое текущее приложение со множеством конечных репозиториев, каждый репозиторий, имеющий свой собственный контекст, будет означать, что данный запрос может иметь 3-10 экземпляров DbContext. Я предполагаю (возможно, неправильно), что это проблематично.


Повторяя вопрос:

Каков правильный способ совместного использования EF DbContext в нескольких хранилищах в веб-приложении MVC? Это разумно/необходимо сделать так, каковы подводные камни, делающие или не делающие это?

Ответ 1

  • DbContext являются дешевыми, а распределенные транзакции - нет.
  • Объекты, привязанные к одному контексту, не могут использоваться в другом контексте (если у вас есть объектные отношения)

Самый простой способ совместного использования контекста - начать использовать инверсию контейнера управления: http://www.codeproject.com/Articles/386164/Get-injected-into-the-world-of-inverted-dependenci

Ответ 2

Я бы выбрал комбинацию между двумя первыми вариантами и в отношении вашего первого варианта, не позволяйте репозиториям сохранять какие-либо изменения (что не рекомендуется делать, Мартин Фаулер говорит, что он сам) и для что он представил образец "Единицы работы".