2010-01-12 3 views
11

В настоящее время я создаю проект ASP.NET MVC с NHibernate в качестве уровня его прочности.Как я могу реализовать надежный шаблон сеанса за запрос в моем проекте, а также сосредоточиться на скрытии информации?

В настоящее время реализована некоторая функциональность, но используются только локальные сеансы NHibernate: каждый метод, который обращается к базе данных (чтение или запись), должен создать экземпляр собственного сеанса NHibernate с помощью предложения «use()».

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

Это подразумевает открытый сеанс NHibernate для каждого запроса до отображения визуализации. Кроме того, одновременные запросы должны поддерживаться (одновременно несколько сеансов).

Как я могу достичь этого как можно чище?

Я искал в Интернете немного и узнал о шаблоне сеанса за запрос. Большинство реализаций, которые я видел, использовали какой-то объект Http * (HttpContext и т. Д.) Для хранения сеанса. Кроме того, использование функций Application_BeginRequest/Application_EndRequest сложное, поскольку они запускаются для каждого HTTP-запроса (aspx-файлы, css-файлы, js-файлы и т. Д.), Когда я хочу только создать экземпляр сеанса один раз для каждого запроса.

Опасность, которую я испытываю, заключается в том, что я не хочу, чтобы мои взгляды или контроллеры имели доступ к сеансам NHibernate (или, в более общем смысле, пространствам и коду NHibernate). Это означает, что я не хочу обрабатывать сеансы на уровне контроллера или в режиме просмотра.

У меня есть несколько вариантов. Какой из них кажется лучшим?

  • Используйте перехватчики (как в GRAILS), которые срабатывают до и после действия контроллера. Они откроют и закрывают сеансы/транзакции. Возможно ли это в мире ASP.NET MVC?
  • Используйте синтаксис CurrentSessionContext, предоставляемый NHibernate в контексте Web. Например, используя this page, я думаю, что это довольно многообещающе, но для контроллеров все еще требуются фильтры.
  • Используйте HttpContext.Current.Items для хранения сеанса запроса. Это, в сочетании с несколькими строками кода в Global.asax.cs, может легко предоставить мне сеанс на уровне запроса. Однако это означает, что зависимости будут вводиться между NHibernate и моими представлениями (HttpContext).

спасибо!

+0

«зависимостей будет закачиваться между NHibernate и моих взглядов» -> это не совсем понятно, что вы имеете в виду с этим, можете ли вы объяснить дальше? –

+0

Если я использую HttpContext для хранения сеанса NHibernate, аспект вида моего приложения MVC будет связан с аспектом доступа к данным (сеанс NHibernate). –

+0

@ggervais: это происходит только в том случае, если вы используете ленивую загрузку в своих представлениях, чего не следует. –

ответ

13

Ну, ребята, после нескольких дней работы я наконец решил использовать HttpContext.Current.Items для загрузки сеанса.

Он отлично работает!

Вот как я это сделал

import System.Web 
class SessionManager { 
    public static ISession GetSession() 
     var session = HttpContext.Current.Items["NHibernateSession"]; 
     if (session == null) { 
      session = ...; // Create session, like SessionFactory.createSession()... 
      HttpContext.Current.Items.Add("NHibernateSession", session); 
     } 
     return session; 
    } 

    public static void CloseSession() 
    { 
     var session = HttpContext.Current.Items["NHibernateSession"]; 
     if (session != null) { 
      if (session.IsOpen) { 
       session.close(); 
      } 
      HttpContext.Current.Items.Remove("NHibernateSession"); 
     } 
    } 
} 

Используя статические методы, предоставляемые этим классом, можно получить сеанс (например, в контроллер), который привязан к текущему HttpContext (текущий веб-запрос). Нам нужен еще один фрагмент кода для вызова метода CloseSession(), когда запрос будет завершен.

В Global.asax.cs:

protected void Application_EndRequest(object sender, EventArgs args) 
{ 
    NHibernateSessionManager.CloseSession(); 
} 

Событие Application_EndRequest автоматически вызывается, когда сеанс будет завершен, поэтому сеанс может быть надлежащим образом закрыл утилизированы. Это полезно, потому что в противном случае мы должны были бы сделать это в каждом контроллере!

+1

Можете ли вы дать более подробную информацию, пожалуйста, тем, кто из нас пытается выяснить, как это установить? –

+0

@ joe-phillips: см. Мое редактирование, я объяснил это! –

+0

Я думаю, что это может создать проблемы, пока вы выполняете модульное тестирование, необходимо позаботиться об этом. Я наткнулся на эту ссылку http://www.prideparrot.com/blog/archive/2012/7/how_to_create_a_custom_session_value_provider, с которой может быть хорошим вариантом. Любые входы были бы хорошими? –

1

Посмотрите на S#arp Architecture. Это очень приятная архитектура для ASP.NET MVC и NHibernate.

2

Использование DI вместе с IoC. Большинство IoC приходят с поведением для каждого запроса.