Я пытаюсь найти лучшее решение для обработки транзакций в веб-приложении, которое использует NHibernate.
Мы используем IHttpModule и в HttpApplication.BeginRequest мы открываем новый сеанс и привязываем его к HttpContext с ManagedWebSessionContext.Bind (context, session); Мы закрываем и отменяем привязку сеанса на HttpApplication.EndRequest.
В нашем базовом классе репозитория мы всегда заключаем транзакцию вокруг наших методов SaveOrUpdate, Delete, Get, как, согласно рекомендациям :
public virtual void Save(T entity)
{
var session = DependencyManager.Resolve<ISession>();
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(entity);
transaction.Commit();
}
}
Но тогда это не сработает, если вам нужно поместить транзакцию где-нибудь, например, в. Служба приложений, включающая несколько вызовов репозитория для сохранения, удаления и т. д.
Итак, мы пытались использовать TransactionScope (я не хотел писать свой собственный менеджер транзакций). Чтобы проверить, что это работает, я использую внешний TransactionScope, который не вызывает .Complete () для принудительного отката:
Сохранение репозитория ():
public virtual void Save(T entity)
{
using (TransactionScope scope = new TransactionScope())
{
var session = DependencyManager.Resolve<ISession>();
session.SaveOrUpdate(entity);
scope.Complete();
}
}
Блок, который использует хранилище:
TestEntity testEntity = new TestEntity { Text = "Test1" };
ITestRepository testRepository = DependencyManager.Resolve<ITestRepository>();
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); выполняется оператор UPDATE с SET Text = "TestCahgned" вместо этого (он должен был быть запущен между BEGIN TRAN и ROLLBACK TRAN). NHibernate считывает значение из кэша уровня 1 и запускает ОБНОВЛЕНИЕ в базу данных. Не ожидаемое поведение !? Из того, что я понимаю, когда бы ни происходил откат в рамках NHibernate, вам также нужно закрыть и отменить привязку текущего сеанса.
Мой вопрос: кто-нибудь знает хороший способ сделать это, используя TransactionScope и ManagedWebSessionContext?