2010-12-16 2 views
1

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

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

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

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

Вот код, я использую в 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(); 
    } 
} 

Редактировать

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

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

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

ответ

3

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

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

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

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

+2

+1: больше информации можно найти в блоге ayende: http://ayende.com/Blog/archive/2009/08/16/what-is-the-cost-of-opening-a-session.aspx – DanP 2010-12-17 17:41:07

Смежные вопросы