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

StackOverflow https://stackoverflow.com/questions/2046168

Вопрос

В настоящее время я создаю 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.Элементы для хранения сеанса запроса.Это, в сочетании с несколькими строками кода в Global.asax.cs, может легко предоставить мне сеанс на уровне запроса.Однако это означает, что зависимости будут внедрены между NHibernate и моими представлениями (HttpContext).

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

Мое "решение" включает в себя использование Unity для ввода сеанса для каждого запроса в контроллеры:

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top