Как правильно организовать открытие/закрытие сессии NHibernate в приложении на ASP.NET
Управление жизненным циклом сессии NHibernate в веб приложении (ASP.NET)
Новые ответы
Я обычно в конструкторе веб приложения (класс, который наследуется от System.Web.HttpApplication) добавляю следующий код:
BeginRequest += (sender, args) =>
{
try
{
CurrentSession = NHibernateManager.OpenSession();
}
catch (Exception ex)
{
_log.Error(ex);
throw;
}
};
EndRequest += (sender, args) =>
{
if (CurrentSession != null) CurrentSession.Dispose();
};
Который при каждом новом запросе создает сессию. И при выполнении запроса уничтожает её. Сессия NHibernate хранится в контексте текущего запроса, и доступна везде в приложении. Для доступа к ней я использую StructureMap, но это уже детали.
public static ISession CurrentSession
{
get { return (ISession)HttpContext.Current.Items["current.session"]; }
set { HttpContext.Current.Items["current.session"] = value; }
}
Для веб-приложения логично привязать время жизни сессии NHibernate ко времени жизни запроса (request). Новая сессия открывается при запросе к серверу и закрывается когда запрос обработан и пользователю вернулся ответ. Практически все web-каркасы поддерживают механизм слежения за жизненным циклом запроса. В ASP.NET можно использовать модули и хендлеры.
Spring.NET уже имеет в своей поставке специальный модуль для этих целей — OpenSessionInViewModule
. Сам механизм привязки сессии к запросу в терминологии Spring называется open session in view (OSIV) pattern.
NHibernate, как и большинство ORM-библиотек, использует шаблон UnitOfWork, чтобы управлять жизненным циклом таких объектов как сессия и транзакция. Обычно, чтобы не привязывать логику отображения к логике ORM, в приложениях пишется собственный класс UnitOfWork
, являющийся оберткой над сущностями ORM (NHibernate). Этот класс выглядит примерно так:
public class UnitOfWork: IUnitOfWork, IDisposable {
public UnitOfWork(){
// Создаем общую сессию NHibernate
}
public void Dispose(){
// Комитим изменения сессии или просто закрываем ее
}
}
Его использование в логике отображения:
using(CreateUnitOfWork()){
var item = new Item();
ItemRepository.Add(item);
}