NHibernate 3.0: TransactionScope и автоматическая очистка
В NHibernate 3.0 FlushMode.Auto
не работает только при выполнении внешней транзакции (то есть без запуска транзакции NHibernate). Должно ли это?
using (TransactionScope scope = new TransactionScope())
{
ISession session = sessionFactory.OpenSession();
MappedEntity entity = new MappedEntity() { Name = "Entity", Value = 20 };
session.Save(entity);
entity.Value = 30;
session.SaveOrUpdate(entity);
// This returns one entity, when it should return none
var list = session.
CreateQuery("from MappedEntity where Value = 20").
List<MappedEntity>();
}
(Пример бесстыдно украденного из этого родственного вопроса)
В источнике NHibernate я вижу, что он проверяет, выполняется ли транзакция (в SessionImpl.AutoFlushIfRequired
), но соответствующий метод (SessionImpl.TransactionInProgress
) не учитывает окружающие транзакции - в отличие от своего двоюродного брата ConnectionManager.IsInActiveTransaction
, который учитывает окружающие транзакции.
5 ответов
Хорошие новости. Благодаря Джеффу Стерну (который хорошо определил проблему) я обновил https://nhibernate.jira.com/browse/NH-3583 и благодаря персоналу NH уже есть исправление и запрос на удаление, поэтому в следующем выпуске 4.1. хх эта проблема будет исправлена.
Вы должны всегда использовать явную транзакцию NHibernate.
using (TransactionScope scope = new TransactionScope())
using (ISession session = sessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
//Do work here
transaction.Commit();
scope.Complete();
}
Я вижу, вы также написали в списке разработчиков NH - хотя это может измениться в будущем, вот как это работает сейчас.
Ответ, предоставленный Диего, не работает, если у вас есть база данных оракула. ( выпущенный вопрос). Сессия session.BeginTransaction не будет выполнена, поскольку соединение уже является частью транзакции.
Похоже, что мы должны написать некоторый код для решения этой проблемы в нашем приложении (WCF,NHibernate, Oracle), но кажется, что NHibernate должен предоставить "из коробки". Так что, если у кого-то есть хороший ответ, он будет очень признателен.
Я нашел ответ на это для оракула. Проверьте это здесь: проблема NHibernate TransactionScope с Oracle 11g
Для меня, я не знаю причину, но принудительное сбрасывание сессии до того, как сессия будет ликвидирована, похоже, сработало для меня. например, используя (сессия) { // делать свою работу
session.Flush(); }
Я проверил, что это работает с моей распределенной транзакцией, так как без этого я всегда получаю "транзакция прервана", когда TransactionScope удаляется.
Даже установить session.FlushMode для Commit не работает для меня.