Как реализовать сеанс NHibernate для каждого запроса без зависимости от NHibernate? - PullRequest
7 голосов
/ 26 мая 2010

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

До сих пор я достиг почти постоянного невежества в своем веб-проекте.Мои классы репозитория (в моем проекте данных) принимают 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 на своем уровне хранилища и хочу использовать запрос сеанса на (http).Поэтому я внедряю ISession в мои конструкторы репозитория (используя structmap).В настоящее время для создания и размещения сессий в каждом запросе мне нужно было ссылаться на NHibernate из моего веб-проекта.Это зависимость, которую я хотел бы удалить.

Спасибо, Бен

Ответы [ 3 ]

3 голосов
/ 26 мая 2010

Почему бы вам не создать модуль 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
        }
    }
}

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

2 голосов
/ 27 мая 2010

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

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

0 голосов
/ 27 мая 2010

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

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

Burrow - это легковесное промежуточное ПО, разработанное для поддержки приложений .Net, использующих NHibernate (возможно, также упоминаемый как NH в этой статье) в качестве платформы ORM. Использование 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. Мне не очень нравится тот факт, что я должен ссылаться на эти три сборки в своем веб-проекте, но по крайней мере я теряю код для управления сессией - все это обрабатывает Барроу.

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

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

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

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

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

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

...