Ленивая инициализация ISession с использованием WebSessionContext / CurrentSessionContext

Я начинаю новый проект с NHibernate 3 и пытаюсь использовать API CurrentSessionContext с WebSessionContext для управления моим объектом ISession.

В предыдущих проектах я всегда справлялся с этим сам, поэтому всякий раз, когда мне требовался объект ISession, я создавал его и сохранял в коллекции HttpContext.Items. Довольно просто, но использование собственного решения (CurrentSessionContext) кажется лучшим вариантом для этого нового проекта.

Когда я управлял объектом, я смог выполнить для него ленивую инициализацию, что означает, что я буду открывать сеанс только тогда, когда он мне нужен, а не в каждом запросе, потому что он мне может не понадобиться, и я буду тратить ресурсы / время, открывая его все время.

Есть ли простой способ сделать это с помощью CurrentSessionContext API?

Вот код, который я использую в HttpModule, отвечающем за это:


public class ContextualSessionModule : IHttpModule
{

    public void Init(HttpApplication context)
    {
        context.BeginRequest += context_BeginRequest;
        context.EndRequest += context_EndRequest;
    }

    public void Dispose()
    {
    }

    private static void context_BeginRequest(object sender, EventArgs e)
    {
        var application = (HttpApplication)sender;
        var context = application.Context;

        BindSession(context);
    }

    private static void BindSession(HttpContext context)
    {
        // Create a new session (it's the beginning of the request)
        var session = SessionBuilderFactory.CurrentSessionFactory.OpenSession();

        // Tell NH session context to use it
        CurrentSessionContext.Bind(session);
    }

    private static void context_EndRequest(object sender, EventArgs e)
    {
        var application = (HttpApplication)sender;
        var context = application.Context;

        UnbindSession(context);
    }

    private static void UnbindSession(HttpContext context)
    {
        // Get the default NH session factory
        var factory = SessionBuilderFactory.CurrentSessionFactory;

        // Give it to NH so it can pull the right session
        var session = CurrentSessionContext.Unbind(factory);

        if (session == null) return;
        session.Flush();
        session.Close();
    }
}

Изменить

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

Я специалист по луковой архитектуре, поэтому объекты моего домена (которые те, кто знает, когда начинать транзакцию) не имеют доступа к инфраструктуре, поэтому они не могут начинать транзакции.

Чтобы решить эту проблему, я использую ленивую инициализацию и всегда запускаю транзакцию при открытии сеанса. Фиксация происходит, когда запрос завершается и исключения не обнаруживаются. Помимо этого, Айенде советует всегда использовать транзакции, даже при запросах. Есть предположения?


person tucaz    schedule 16.12.2010    source источник


Ответы (1)


Не отвечая прямо на ваш вопрос, я думаю: почему?

Сеанс - это легкий объект. Если вы его не используете, он просто инициализирует некоторые внутренние структуры, но не открывает соединение с БД или что-то еще.

Есть несколько примеров (только Google), чтобы избежать открытия сеансов для статических объектов, чтобы сэкономить немного времени / памяти. В остальном оно того не стоит, если только ваше профилирование не показывает, что это вредит вашей производительности.

Обновление: для транзакционных нужд ознакомьтесь с реализацией CpBT в uNhAddIns.

person Diego Mijelshon    schedule 17.12.2010
comment
+1: дополнительную информацию можно найти в блоге ayende: ayende.com/Blog/archive/2009/08/16/ - person DanP; 17.12.2010
comment
Отличная ссылка @DanP, запомнил пост, но не заголовок. - person Diego Mijelshon; 17.12.2010
comment
Похоже, это решает проблему! Я никогда не искал, сколько будет стоить открытие сеанса. Я подумал (из ниоткуда), что он открыл соединение с базой данных. Большое спасибо - person tucaz; 17.12.2010
comment
Я отредактировал вопрос, чтобы добавить еще одну проблему, связанную с этим подходом. - person tucaz; 18.12.2010