У кого-либо есть какие-либо подсказки или лучшие практики относительно того, как Autofac помогают, может управлять Экземпляром NHibernate ISession (в случае приложения MVC ASP.NET)?
Я не слишком хорошо знаком с тем, как следует обрабатывать сеансы NHibernate. Тем не менее, Autofac имеет отличную обработку времени жизни экземпляра ( область видимости и детерминированное удаление ). Некоторые связанные ресурсы - это эта статья и этот вопрос . Поскольку вы находитесь в области ASP.Net MVC, убедитесь, что вы также изучили материалы по интеграции MVC .
Чтобы проиллюстрировать суть дела, вот краткий пример того, как можно использовать фабричные делегаты Autofac и универсальный Owned
, чтобы получить полный контроль над временем жизни экземпляра:
public class SomeController
{
private readonly Func<Owned<ISession>> _sessionFactory;
public SomeController(Func<Owned<ISession>> sessionFactory)
{
_sessionFactory = sessionFactory;
}
public void DoSomeWork()
{
using (var session = _sessionFactory())
{
var transaction = session.Value.BeginTransaction();
....
}
}
}
Настройка контейнера, чтобы заставить это работать, довольно просто.Обратите внимание, что нам не нужно ничего делать, чтобы получить типы Func <>
и Owned <>
, они автоматически становятся доступными с помощью Autofac:
builder.Register(c => cfg.BuildSessionFactory())
.As<ISessionFactory>()
.SingleInstance();
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession());
Обновление: Я считаю, что согласно этому руководству NHibernate время жизни экземпляра сеанса должно соответствовать времени жизни «единицы работы». Таким образом, нам нужен какой-то способ управления как при создании экземпляра сеанса, так и при удалении сеанса.
С Autofac мы получаем этот контроль, запрашивая Func <>
вместо типа напрямую. Если не использовать Func <>
, потребуется заранее создать экземпляр сеанса до создания экземпляра контроллера.
Далее, по умолчанию в Autofac у экземпляров есть время жизни своего контейнера. Поскольку мы знаем, что нам нужны полномочия для удаления этого экземпляра, как только единица работы будет выполнена, мы запрашиваем экземпляр Owned
. В этом случае удаление принадлежащего экземпляра приведет к немедленному удалению базового сеанса.
Edit: Похоже, что Autofac и, возможно, другие контейнеры могут правильно определить время жизни. Если это так, то действуйте.
Не стоит использовать ваш IoC-контейнер для прямого управления сессиями. Время жизни вашей сессии должно соответствовать вашей единице работы (границе транзакции). В случае веб-приложения это почти наверняка должно быть время жизни веб-запроса.
Наиболее распространенным способом достижения этого является HttpModule, который одновременно создает сессию и начинает транзакцию, когда начинается запрос, а затем фиксирует, когда запрос завершен. Я бы попросил HttpModule зарегистрировать сессию в коллекции HttpContext.Items.
В вашем IoC контейнере вы могли бы зарегистрировать что-то вроде HttpContextSessionLocator против ISessionLocator.
Я должен упомянуть, что ваша общая обработка ошибок должна находить текущую сессию и автоматически откатывать транзакцию, иначе вы можете совершить половину работы.