NHibernate, транзакции и TransactionScope

Я пытаюсь найти лучшее решение для обработки транзакций в веб-приложении, которое использует NHibernate.

Мы используем IHttpModule и в HttpApplication.BeginRequest мы открываем новый сеанс и привязываем его к HttpContext с ManagedWebSessionContext.Bind (context, session); Мы закрываем и развязываем сеанс по HttpApplication.EndRequest.

В нашем базовом классе репозитория мы всегда обертываем транзакцию вокруг наших методов SaveOrUpdate, Delete, Get, например, согласнолучшая практика:

        public virtual void Save(T entity)
        {
          var session = DependencyManager.Resolve();
          using (var transaction = session.BeginTransaction())
          {
            session.SaveOrUpdate(entity);
            transaction.Commit();
          }
        }

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

Так что мы пытались использовать TransactionScope (я нене хочу писать свой собственный менеджер транзакций). Чтобы проверить, что это работает, я использую внешний TransactionScope, который неt вызвать .Complete () для принудительного отката:

Сохранение репозитория ():

    public virtual void Save(T entity)
    {
        using (TransactionScope scope = new TransactionScope())
        {
            var session = DependencyManager.Resolve();
            session.SaveOrUpdate(entity);
            scope.Complete();
        }   
    }  

Блок, который использует репозиторий:

        TestEntity testEntity = new TestEntity { Text = "Test1" };
        ITestRepository testRepository = DependencyManager.Resolve();

        testRepository.Save(testEntity);

        using (var scope = new TransactionScope())
        {
          TestEntity entityToChange = testRepository.GetById(testEntity.Id);

          entityToChange.Text = "TestChanged";
          testRepository.Save(entityToChange);
        }

        TestEntity entityChanged = testRepository.GetById(testEntity.Id);

        Assert.That(entityChanged.Text, Is.EqualTo("Test1"));

Это нет работа. Но для меня, если NHibernate поддерживает TransactionScope, это будет! Что происходит, так это то, что ROLLBACK вообще отсутствует в базе данных, но когда testRepository.GetById (testEntity.Id); оператор выполняется ОБНОВЛЕНИЕ с SET Text = "TestCahgned» вместо этого (должен был быть запущен между BEGIN TRAN и ROLLBACK TRAN). NHibernate считывает значение из кэша уровня 1 и запускает ОБНОВЛЕНИЕ в базу данных. Не ожидаемое поведение !? Из того, что я понимаю, когда бы ни происходил откат в рамках NHibernate, вам также нужно закрыть и отменить привязку текущего сеанса.

Мой вопрос: кто-нибудь знает хороший способ сделать это, используя TransactionScope и ManagedWebSessionContext?

Ответы на вопрос(4)

Ваш ответ на вопрос