Я провел остаток вечера, читая вопросы StackOverflow, а также некоторые записи в блогах и ссылки на тему. Все они оказались очень полезными, но я все еще чувствую, что они действительно не отвечают на мой вопрос.
Итак, я разрабатываю простое веб-приложение. Я хотел бы создать многоразовый слой доступа к данным, который впоследствии можно будет повторно использовать в других решениях. 99% из них будут веб-приложениями. Это, по-видимому, является хорошим оправданием для меня, чтобы выучить NHibernate и некоторые модели вокруг него.
Мои цели следующие:
- Я не хочу, чтобы уровень бизнес-логики ничего не знал о внутренней работе базы данных, а также о NHibernate.
- Я хочу, чтобы уровень бизнес-логики имел наименьшее количество предположений относительно уровня доступа к данным.
- Я хочу, чтобы уровень доступа к данным был как можно более простым и простым в использовании. Это будет простой проект, поэтому я не хочу ничего лишнего.
- Я хочу, чтобы уровень доступа к данным был как можно более неинтрузивным.
Помня об этом, я решил использовать популярный шаблон репозитория. Я читал об этой теме на этом сайте и в различных блогах разработчиков, и я слышал кое-что о единице шаблона работы.
Я также осмотрелся и проверил различные реализации. (В том числе FubuMVC contrib и SharpArchitecture и т.д. В некоторых блогах). Я узнал, что большинство из них работают по тому же принципу: они создают "единицу работы", которая создается при создании экземпляра репозитория, они начинают транзакцию, делать вещи и совершать, а затем начинать все заново. Итак, только один ISession
за Repository
и что он. Затем клиентский код должен создавать экземпляр репозитория, делать с ним все, а затем распоряжаться.
Эта модель использования не соответствует моей потребности быть максимально упрощенной, поэтому я начал думать о чем-то еще.
Я выяснил, что в NHibernate уже есть что-то, что делает ненужные реализации "единицы работы", и это класс CurrentSessionContext
. Если я правильно настрою контекст сеанса и сделаю очистку, когда это необходимо, я буду рад.
Итак, я придумал это:
У меня есть внутренний статический класс NHibernateHelper
. Во-первых, он имеет статическое свойство CurrentSessionFactory
, которое при первом вызове создает экземпляр factory и сохраняет его в статическом поле. (Один ISessionFactory
за один AppDomain
достаточно хорош.) Затем, что более важно, оно имеет статическое свойство CurrentSession
, которое проверяет, существует ли ISession
, привязанный к текущему контексту сеанса, а если нет, создается один, и связывает его, и он возвращается с ISession
, привязанным к текущему контексту сеанса.
Потому что он будет использоваться в основном с WebSessionContext
(так что один ISession
за HttpRequest
, хотя для модульных тестов я настроил ThreadStaticSessionContext
), он должен работать без проблем. И после создания и привязки ISession
он перехватывает обработчик событий в событие HttpContext.Current.ApplicationInstance.EndRequest
, который позаботится о том, чтобы очистить ISession
после завершения запроса. (Конечно, он делает это только в том случае, если он действительно работает в веб-среде.)
Таким образом, при всех этих настройках NHibernateHelper
всегда сможет вернуть допустимый ISession
, поэтому нет необходимости создавать экземпляр экземпляра репозитория для "единицы работы" для правильной работы. Вместо этого Repository
является статическим классом, который работает с ISession
из свойства NHibernateHelper.CurrentSession
и предоставляет функциональность с помощью общих методов.
Итак, в основном, у меня были два очень ленивых синглета.
Мне любопытно, что вы думаете об этом? Является ли это правильным способом мышления, или я полностью отсюда?
EDIT:
Я должен указать, что класс NHibernateHelper является внутренним, поэтому почти невидимым для потребителей репозитория.
Другая идея заключается в том, что для интродукции инъекции зависимостей в решение необходимо создать интерфейс с именем IDataProvider
и создать экземпляр одного экземпляра этого при первом вызове класса Repository
. (Тем не менее, внедряющий код должен уметь также учитывать концепцию контекста.)
РЕДАКТИРОВАТЬ 2:
Кажется, что многим нравится моя идея, но в ответах все еще слишком мало.
Могу ли я предположить, что это правильный способ использования NHibernate?: P