Я запускаю новый проект с 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, поэтому мои объекты домена (те, кто знает, когда начинать транзакцию) не имеют доступа к инфраструктуре, поэтому они не могут запускать транзакции.
Чтобы решить эту проблему, я использую ленивую инициализацию и всегда начинаю транзакцию при открытии сеанса. Заключение происходит, когда запрос заканчивается, и никаких исключений не было. Кроме того, существует совет Айенде всегда использовать транзакции, даже при запросе. Есть предположения?
+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