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