Я потратил остальную часть вечера, читая вопросы о StackOverflow и также некоторые записи в блоге и ссылки о предмете. Все они оказались очень полезными, но я все еще чувствую, что они действительно не отвечают на мой вопрос.
Так, я разрабатываю простое веб-приложение. Я хотел бы создать допускающий повторное использование уровень доступа к данным, который я могу позже снова использовать в других решениях. 99% из них будут веб-приложениями. Это, кажется, хорошее оправдание за меня изучить NHibernate и некоторые шаблоны вокруг этого.
Мои цели следующие:
Будет все это в памяти, я решил использовать популярный шаблон репозитория. Я читал об этом предмете на этом сайте и на различных блогах dev, и я слышал некоторый материал о шаблоне единицы работы.
Я также озирался и проверил различные реализации. (Включая FubuMVC contrib, и SharpArchitecture и материал на некоторых блогах.) Я узнал, что большинство из них работает с тем же принципом: Они создают "единицу работы", которая инстанцируют, когда репозиторий инстанцируют, они запускают транзакцию, действительно наполните, и фиксация, и затем запуститесь снова и снова. Так, только один ISession
на Repository
и вот именно. Затем клиентский код должен инстанцировать репозитория, действительно наполните им и затем расположите.
Этот шаблон использования не удовлетворяет мои потребности того, чтобы быть максимально упрощенным, таким образом, я начал думать о чем-то еще.
Я узнал, что NHibernate уже имеет что-то, что делает пользовательские реализации "единицы работы" ненужными, и это CurrentSessionContext
класс. Если я настраиваю контекст сессии правильно и делаю уборку при необходимости, я хорош для движения.
Так, я придумал это:
У меня есть внутренний статический названный класс NHibernateHelper
. Во-первых, этому назвали статическое свойство CurrentSessionFactory
, который на первый вызов, инстанцирует фабрики сессии и хранит его в статическом поле. (Один ISessionFactory
на одного AppDomain
достаточно хорошо.) Затем что еще более важно, это имеет a CurrentSession
статическое свойство, которое проверяет, существует ли ISession
связанный с текущим контекстом сессии, и в противном случае создает один и связывает его, и это возвращается с ISession
связанный с текущим контекстом сессии.
Поскольку это будет использоваться главным образом с WebSessionContext
(таким образом, один ISession
на HttpRequest
, хотя для модульных тестов, я настроил ThreadStaticSessionContext
), это должно работать беспрепятственно. И после создания и привязки ISession
, это сцепляет обработчик событий с HttpContext.Current.ApplicationInstance.EndRequest
событие, которое заботится о чистке ISession
после того, как запрос заканчивается. (Конечно, это только делает это, если это действительно работает в веб-среде.)
Так, со всем этим настроенным, NHibernateHelper
будет всегда мочь возвратить допустимое ISession
, таким образом, нет никакой потребности инстанцировать экземпляра Репозитория для "единицы работы" для работы правильно. Вместо этого Repository
статический класс, который работает с ISession
от NHibernateHelper.CurrentSession
свойство, и выставляет функциональность через это общими методами.
Так, в основном я закончил с двумя очень ленивыми одиночными элементами.
Мне любопытно, что Вы думаете об этом? Действительно ли это - допустимый образ мыслей или является мной полностью от дорожки здесь?
Править:
Я должен указать, что класс NHibernateHelper является внутренним, так в значительной степени невидимым для потребителей репозитория.
Другая идея, чтобы к intoduce внедрению зависимости в решение, должен сделать интерфейс названным IDataProvider
, и инстанцируйте одного экземпляра этого на первый вызов к Repository
класс. (Однако код реализации должен смочь заботиться понятие контекста также.)
РЕДАКТИРОВАНИЕ 2:
Кажется, что многие люди как моя идея, но существует все еще слишком мало мнений об этом в ответах.
Я могу предположить, что это - правильный способ использовать NHibernate, затем?:P
Как бы то ни было, Sharp Architecture делает более или менее именно то, что вы предлагаете. В итоге он доставляет один сеанс для каждого HTTP-запроса (точнее, один сеанс для каждой базы данных на каждый HTTP-запрос). Ваш подход, безусловно, действителен, и он также обеспечивает один сеанс на запрос. Я предпочитаю более чистый объектно-ориентированный подход SharpArch через DI, а не статические репозитории и вспомогательный класс.
Мы смешали приложения ASP.NET/Windows Forms, и лучшее решение, которое я нашел, - это внедрение зависимостей вручную через конструктор репозитория. То есть каждый класс репозитория имеет единственный общедоступный конструктор, которому требуется ISession. Это позволяет приложению полностью контролировать границы единицы работы и транзакции. Это просто и эффективно. У меня также есть очень маленькая вспомогательная сборка NHibernate, которая настраивает фабрики сеансов и предоставляет методы для открытия обычного или контекстного сеанса.
В S # arp Architecture мне нравится много вещей, и я думаю, что стоит изучить, как она работает, но я обнаружил, что она слишком продумана для моих вкусов.