Как я могу реализовать надежный шаблон сеанса в запросе в моем проекте, сосредоточившись на сокрытии информации? - PullRequest
11 голосов
/ 12 января 2010

В настоящее время я создаю проект ASP.NET MVC с NHibernate в качестве слоя персистентности.

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

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

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

Как мне достичь этого максимально чисто?

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

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

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

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

Большое спасибо!

Ответы [ 5 ]

13 голосов
/ 19 января 2010

Ну, ребята, после нескольких дней работы я наконец решил использовать 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 автоматически вызывается по завершении сеанса, поэтому сеанс может быть надлежащим образом закрыт для удаления. Это полезно, потому что в противном случае нам пришлось бы делать это на каждом контроллере!

2 голосов
/ 17 мая 2010

Мое "решение" предполагает использование Unity для внедрения сеанса по запросу в контроллерах:

http://letsfollowtheyellowbrickroad.blogspot.com/2010/05/nhibernate-sessions-in-aspnet-mvc.html

2 голосов
/ 12 января 2010

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

1 голос
/ 12 января 2010

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

http://weblogs.asp.net/srkirkland/archive/2009/09/03/asp-net-mvc-transaction-attribute-using-nhibernate.aspx

1 голос
/ 12 января 2010

Взгляните на S # arp Architecture . Это очень хорошая архитектура для ASP.NET MVC и NHibernate.

...