Является ли статический репозиторий правильным способом использования NHibernate?

Я провел остаток вечера, читая вопросы 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

Ответ 1

Для чего стоит, Sharp Architecture делает более или менее точно то, что вы предлагаете. Он заканчивает доставку одного сеанса на HTTP-запрос (точнее, один сеанс на каждую базу данных на HTTP-запрос). Ваш подход, безусловно, действителен и также обеспечивает один сеанс для каждого запроса. Я предпочитаю SharpArch clean OO-подход через DI с использованием статических репозиториев и вспомогательного класса.

Ответ 2

У нас смешанные приложения ASP.NET/Windows Forms, и лучшим решением, которое я нашел, является выполнение ручного ввода зависимостей через конструктор репозитория. То есть, каждый класс репозитория имеет единственный публичный конструктор, который требует ISession. Это позволяет приложению иметь полный контроль над единицами работы и границ транзакций. Это просто и эффективно. У меня также есть небольшая вспомогательная сборка NHibernate, которая настраивает сеансовые фабрики и предоставляет методы для открытия регулярного или контекстного сеанса.

В архитектуре S # arp есть много вещей, и я думаю, что стоит изучить, как это работает, но я нашел, что это слишком зашифровано для моих вкусов.