Как известно основными объектами, с которыми приходится работать в NHibernate это Session и SessionFactory. При этом SessionFactory должен быть один на все приложение, поскольку его создание обходится дорого, а Session – дешевый для создания объект.
Можно рассмотреть следующий вариант, объект Session создается по необходимости – т.е. на каждый запрос к базе мы получаем новый экземпляр сессии. Но в этом сценарии мы теряем кеш первого уровня, получаем сложности с транзакциями и т.д. Наиболее распространен подход Session Per Web Request. В этом случае сессия создается в начале обработки запроса, и удаляется по завершению.
В этом посте я покажу как очень просто реализовать это с использованием Castle Windsor. Для этого добавляем один класс, который будет отвечать за конфигурацию SessionFactory:
public class NHibernateConfiguration
{
public ISessionFactory CreateSessionFactory()
{
FluentConfiguration configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(cs=>cs.FromConnectionStringWithKey("dbConnection")))
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf<CategoryMap>());
return configuration.BuildSessionFactory();
}
}
Далее, добавив ссылки на Castle.Core, Castle.MicroKernel и Castle.Windsor создаем класс, который настроит правила работы с SessionFactory и Session:
public static class ServiceLocaterInitializer
{
/// <summary>
/// Initializes Castle Windsor.
/// </summary>
public static void Init()
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
container.Register(Component.For<ISessionFactory>()
.LifeStyle.Singleton
.UsingFactoryMethod(() => new NHibernateConfiguration().CreateSessionFactory()));
container.Register(Component.For<ISession>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>().OpenSession()));
}
}
Чтобы это заработало необходимо добавить http модуль в веб конфиге:
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.MicroKernel" />
Далее, чтобы получить объект Session достаточно сделать следующий вызов:
var session = container.Resolve<ISession>();
Жизненным циклом объектов Castle будет управлять сам.
Уважаемый, Адрей ! Подскажите, а когда нужно выполнить ServiceLocaterInitializer.Init()
ReplyDeleteЯ бы это делал в Application_Start
ReplyDeleteХороший пост! Еще хотелось бы статью с простым примером реализации repository pattern на Nhibernate и использованием iocконтейнера.
ReplyDelete