2

Я пытаюсь справиться с NHibernate, Fluent NHibernate и Spring.Реализация репозиториев с использованием NHibernate и Spring.Net

После домена управляемых дизайн принципалов, я пишу стандартную многоуровневую веб-приложение, состоящее из:

  • презентационного уровня (ASP.Net)
  • бизнес-уровня, включающий:
    • прикладной уровень (в основном набор методов, видимых для уровня UI)
    • интерфейсы репозитория и компоненты домена (используемые прикладным уровнем)
  • настойчивости уровень (в основном реализация хранилища интерфейсов, определенных в бизнес-уровне)

Я хотел бы помощи в определении способа создания экземпляра NHibernate ISession таким образом, что он может использоваться несколько репозитории на протяжении всего срока службы одного запроса на бизнес-уровень. В частности, я хотел бы:

  • позволяет экземпляр ISession и любая сделка будут контролироваться outwith хранилища реализации

  • позволяет ISession (возможно, по какому-либо аспекту в рамках МОК, перехватчик?) экземпляр, доступный для хранилищ в удобном для восприятия образом (возможно, путем инъекции или с помощью некоторой общей абстракции контекста)

  • избегать создания ненужных транзакций (т.е. когда выполняются только операции только для чтения)

  • позволяет мне писать тесты, которые используют SQLLite

  • позволяют мне использовать Fluent NHibernate

  • позволяет реализации хранилища оставаться в неведении принимающей среды. Я еще не знаю, будет ли businese-уровень работать в процессе с уровнем представления или будет размещаться отдельно под WCF (в IIS), поэтому я не хочу слишком привязывать свой код к HTTP-контексту (например,).

Моя первая попытка решить эту проблему использовала шаблон реестра; сохраняя экземпляр ISession в свойстве ThreadStatic. Однако последующее чтение показало, что это не лучшее решение (поскольку, как мне кажется, ASP.Net может переключать поток в жизненном цикле страницы).

Любые мысли, решения частей, названия паттернов, указатели на современные образцы (NHibernate 2) будут с благодарностью восприняты.

ответ

1

Я не использовал Spring.NET, поэтому не могу прокомментировать это. Однако остальное звучит замечательно (или, может быть, не так замечательно, мы вряд ли первыми реализуем эти вещи;) похожи на мой собственный опыт. Мне тоже не удалось найти «Истинную лучшую практику», поэтому я просто читал столько, сколько мог, и придумал собственную интерпретацию.

В моей ситуации я хотел бы, чтобы управление транзакциями/сеансами было внешним по отношению к репозиторию, а также препятствовало возникновению проблем с хранилищем (из-за того, что код, использующий репозиторий, не должен знать, что он использует NHibernate внутри себя и должен не нужно ничего знать об управлении сеансом NHibernate). В моем случае было решено, что транзакции будут созданы по умолчанию, чтобы разработчики не забыли их, поэтому мне пришлось иметь механизм выхода только для чтения. Я пошел с шаблоном Unit of Work с хранилищем экземпляров NHibernate ISession внутри. Телефонный код (я также создал DSL интерфейс для UOW) может выглядеть примерно так:

using (var uow = UoW.Start().ReadOnly().WithHttpContext() 
     .InNewScope().WithScopeContext(ScopeContextProvider.For<CRMModel>()) 
{ 
    // Repository access 
} 

На практике это может быть столь же коротким, как UoW.Start() в зависимости от того, сколько контекст уже доступен. Часть HttpContext относится к месту хранения для UoW, что неудивительно, что в этом случае HttpContext. Как вы уже упоминали, для ASP.NET-приложения HttpContext - это самое безопасное место для хранения вещей. ScopeContextProvider в основном обеспечивает правильный контекст данных для UoW (экземпляр ISession для соответствующей базы данных/сервера, другие настройки). Концепция «ScopeContext» также упрощает вставку контекста области «тест».

Выполнение этого маршрута делает репозитории явно зависимыми от интерфейса UoW. На самом деле, возможно, вы сможете отвлечь его, но я не уверен, что вижу пользу. Я имею в виду, что каждый метод репозитория извлекает текущий экземпляр UoW, а затем вытаскивает объект ISession (или просто SqlConnection для тех методов, которые не используют NHibernate) для запуска запроса/операции NHibernate. Это работает для меня, хотя потому, что также кажется идеальным временем, чтобы убедиться, что текущий UoW не доступен только для чтения для методов, которые могут потребоваться для запуска CRUD.

В целом, я считаю, что это один подход, который решает все пункты:

  • Позволяет управление сеансом быть внешним по отношению к репозиторию
  • ISession контекст может быть издевался или указал на поставщике контекста для теста среда
  • Избегает ненужные операции (ну, вы должны инвертировать, что я сделал, и есть .Transactional() вызова или что-то)
  • Я не могу понять, почему вы не могли проверить с SQLite, так что это скорее NHibernate озабоченности
  • Я использую Fluent NHibernate сам
  • Позволяет хранилище не знать принимающей среды (то есть, вызывающий хранилище контролирует контекст хранения UOW)

Что касается реализации UOW, я частично ногами, чтобы не оглядываться больше, прежде чем я начал. Есть проект под названием machine.uow, который, как я понимаю, довольно популярен и хорошо работает с NHibernate. Я не играл с этим много, поэтому не могу сказать, решает ли он все мои требования так же аккуратно, как тот, который я написал сам, но он также мог бы сэкономить время разработки.

Возможно, мы получим некоторые комментарии относительно того, где я пошла не так, или как улучшить ситуацию, но я надеюсь, что это по крайней мере полезно в некотором роде.

Для справки, стек программного обеспечения я использую:

  • ASP.NET MVC
  • Fluent NHibernate на вершине NHibernate
  • Ninject для инъекций зависимостей
1

То, что вы описываете, поддерживается каркасом Spring.NET почти из коробки. Только для FluentNHibernate вам нужно добавить пользовательский SessionFactory (не много кода, посмотрите здесь: Using Fluent NHibernate in Spring.NET) на Spring.NET.

Каждый репозиторий может использовать один и тот же ISession, просто вставлять SessionFactory в свои репозитории и использовать службы транзакций Spring.NET.

Просто попробуйте, у них довольно подробная документация imho.

+0

Что касается FluentNhibernate, то есть также открытая jira: http://jira.springframework.org/browse/SPRNET-1232 Дополнительными источниками для песчаных может быть Документация: http://www.springframework.net/doc- last/reference/html/nh-quickstart.html Для IntegrationTesting suppport см. http://www.springframework.net/doc-latest/reference/html/testing.html#unit-testing. – tobsen

Смежные вопросы