Как известно основными объектами, с которыми приходится работать в 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