Как я могу реализовать сессию NHibernate на запрос без зависимости от NHibernate?

Я поднял этот вопрос прежде, но все еще изо всех сил пытаюсь найти пример, что я могу получить голову вокруг (только скажите мне смотреть на проект Архитектуры S#arp по крайней мере без некоторых направлений).

До сих пор я достиг близкого незнания постоянства в своем веб-проекте. Мои классы репозитория (в моем проекте данных) берут ISession в конструкторе:

public class ProductRepository : IProductRepository
{
    private ISession _session;
    public ProductRepository(ISession session) {
        _session = session;
    }

В моем global.asax я выставляю текущую сессию, и создаю и располагаю сессию на beginrequest и endrequest (это - то, где у меня есть зависимость от NHibernate):

    public static ISessionFactory SessionFactory = CreateSessionFactory();

    private static ISessionFactory CreateSessionFactory() {
        return new Configuration() 
            .Configure()
            .BuildSessionFactory();
    }

    protected MvcApplication()  {
        BeginRequest += delegate {
            CurrentSessionContext.Bind(SessionFactory.OpenSession());
        };
        EndRequest += delegate {
            CurrentSessionContext.Unbind(SessionFactory).Dispose();
        };
    }

И наконец мой реестр StructureMap:

    public AppRegistry() {
        For<ISession>().TheDefault
            .Is.ConstructedBy(x => MvcApplication.SessionFactory.GetCurrentSession());

        For<IProductRepository>().Use<ProductRepository>();
    }

Казалось бы, что мне нужны мои собственные универсальные реализации ISession и ISessionFactory, который я могу использовать в своем веб-проекте и ввести в свои репозитории?

Так просто для уточнения - я использую NHibernate в своем слое репозитория и хочу использовать session-per-(http) запрос. Поэтому я ввожу ISession в своих конструкторов репозитория (использующий structuremap). В настоящее время, чтобы создать и расположить сессии в каждом запросе я должен был сослаться на NHibernate из своего веб-проекта. Это - зависимость, которую я хотел бы удалить.

Спасибо, Ben

7
задан Ben Foster 26 May 2010 в 13:37
поделиться

3 ответа

Почему бы вам не создать IHttpModule и не выполнить его создание и размещение там (вероятно, в Begin_Request и End_Request событий), а поместить IHttpModule внутрь проекта, который имеет вашу зависимость NHibernate. Например.

namespace MyWebApp.Repository.NHibernateImpl
{
    public class NHibernateModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(Context_BeginRequest);
            context.EndRequest += new EventHandler(Context_EndRequest);
        }

        private void Context_BeginRequest(object sender, EventArgs e)
        {
            // Create your ISession
        }

        private void Context_EndRequest(object sender, EventArgs e)
        {
            // Close/Dispose your ISession
        }

        public void Dispose()
        {
            // Perhaps dispose of your ISessionFactory here
        }
    }
}

Может быть, есть лучший способ, мне интересно узнать и об этом, так что есть ли альтернативные предложения?

3
ответ дан 7 December 2019 в 12:15
поделиться

Спасибо всем за помощь. Немного больше исследований привело меня к проекту NHibernate Burrow.

Из проекта FAQ ( http://nhforge.org/wikis/burrow/faq.aspx ):

Burrow - это легкое промежуточное программное обеспечение, разработанное для поддержки приложений .Net, использующих NHibernate (возможно, также называется NH в этой статье) как ORM framework. Использование Asp.net с NHibernate может быть проблемой из-за того, что NHibernate - это среда с отслеживанием состояния, а Asp.net - среда без отслеживания состояния.Burrow может помочь решить этот конфликт, предоставляя расширенное и интеллектуальное управление сеансами / транзакциями и другие средства.

Мне пришлось преодолеть несколько препятствий, чтобы заставить его работать в моем проекте. Поскольку в текущем выпуске используется старая версия NHibernate, мне пришлось загрузить последний исходный код из магистрали, открыть в VS, добавить ссылки на последнюю версию NHibernate и перекомпилировать (к счастью, без ошибок).

Я тестировал NHibernate Burrow несколькими способами.

1) Продолжить внедрение ISession в мои репозитории

Для этого мне пришлось добавить ссылки на NHibernate, NHibernate.Burrow и NHibernate.Burrow.WebUtil в мой проект MVC.

В web.config мне пришлось настроить Burrow (см. http://nhforge.org/wikis/burrow/get-started.aspx ), а затем в моем реестре StructureMap добавить следующее:

       For<ISession>()
            .TheDefault.Is
            .ConstructedBy(x => new NHibernate.Burrow.BurrowFramework().GetSession());          

Мне нравится этот подход, поскольку он означает, что мои репозитории (или контроллеры) не связаны с Burrow. Мне не очень нравится тот факт, что я должен ссылаться на эти три сборки в моем веб-проекте, но, по крайней мере, я теряю код для управления сеансом - всем этим занимается Burrow.

2) Второй подход заключался бы в установке ISession в конструкторах моих репозиториев следующим образом:

    public ProductRepository() : 
        this(new BurrowFramework().GetSession()) { }

    public ProductRepository(ISession session) {
        _session = session;
    }

Я все еще могу переопределить ISession, делая мои репозитории тестируемыми. Тогда у меня есть прямая зависимость от Burrow, но, может быть, это не так уж и плохо?

С другой стороны, единственная сборка, на которую мне нужно ссылаться из моего веб-проекта, - это NHibernate.Burrow.WebUtils.

Интересно посмотреть, кто из двух человек пойдет на это и почему.

0
ответ дан 7 December 2019 в 12:15
поделиться

На мой взгляд, вы должны принять ISession и работать с ним напрямую. Проблема многих реализаций session-per-request в том, что они откладывают фиксацию изменений в базе данных до окончания HTTP-запроса. Если транзакция завершится неудачно, все, что вы можете сделать в этот момент, это направить пользователя на страницу общей ошибки. Гораздо лучше управлять транзакцией на странице, чтобы можно было более эффективно отлавливать и обрабатывать ошибки. Если вы пойдете этим путем, то для управления транзакцией вам потребуется доступ к ISession или обертке.

Кроме того, в какой-то момент вашему приложению, вероятно, понадобится использовать свойства или методы, открытые ISession, особенно Merge и Load.

2
ответ дан 7 December 2019 в 12:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: