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

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

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

Ответ 1

Ну, ребята, после нескольких дней работы я решил использовать 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

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

Ответ 4

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