Ленивый инициализация ISession с использованием WebSessionContext/CurrentSessionContext
-
11-10-2019 - |
Вопрос
Я начинаю новый проект с Nhibernate 3, и я пытаюсь использовать API CurrentSessionContext с WebSessionContext для управления моим объектом ISession.
В предыдущих проектах я всегда справлялся с этим, поэтому, когда мне нужен объект 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();
}
}
Редактировать
Диего в значительной степени прибил это, но я подумал немного больше об этом, и я вспомнил основную причину, по которой я сам реализовал этот контроль: транзакции.
Я Луковая архитектура Парень, так что мои объекты домена (которые являются теми, кто знает, когда начинать транзакцию) не имеют доступа к инфраструктуре, поэтому они не могут начать транзакции.
Чтобы решить это, я использую ленивую инициализацию и всегда начинаю транзакцию при открытии сеанса. Количество происходит, когда заканчивается запрос, и никаких исключений не было поймано. Кроме того, есть совет Айенде всегда использовать транзакции, даже при запросе. Какие-нибудь мысли?
Решение
В то время как не напрямую Отвечая на ваш вопрос, я думаю: Почему?
Сеанс - это легкий объект. Если вы не используете его, он просто инициализирует некоторые внутренние структуры, но не открывает соединение БД или что -то в этом роде.
Есть несколько примеров вокруг (только Google), чтобы избежать открытия сеансов для статических объектов, чтобы сэкономить немного времени/памяти. Кроме этого, это может не стоить того, если ваше профилирование не показывает, что это вредит вашей производительности.
ОБНОВЛЕНИЕ: Для потребностей в транзакциях посмотрите на реализацию CPBT в Unkaddins.