2012-05-15 2 views
4

У меня есть код, который выглядит следующим образом:NHibernate ExecuteUpdate не участвует в текущей транзакции?

using (var session = this.sessionCreator.OpenSession()) 
using (var transaction = session.BeginTransaction()) 
{ 
    session.SaveOrUpdate(anObject); 
    session.CreateSQLQuery(sql) 
     .ExecuteUpdate(); 
    transaction.Commit(); 
} 

Удивительно, что SQL-запрос выполняется перед anObject сохраняется. По-видимому, команда ExecuteUpdate не участвует в текущей транзакции. Есть ли способ получить обновление в транзакции?

ответ

5

Операции NHibernate не совпадают с транзакциями БД; структура не имеет возможности узнать, какие объекты или какие данные влияет на ваш ExecuteUpdate, и, следовательно, автоматически не очищает сеанс между SaveOrUpdate (который может быть отложен в зависимости от FlushMode сеанса) и CreateSQLQuery (который всегда является непосредственным, если вы используете ExecuteUpdate).

Вообще говоря, если вы комбинируя NHibernate логику с логикой низкого уровня SQL (хранимые процедуры и т.д.), то вы будете хотеть использовать TransactionScope для того, чтобы гарантировать атомарность:

using (var tsc = new TransactionScope()) 
using (var session = sessionFactory.OpenStatelessSession()) 
using (var transaction = session.BeginTransaction()) 
{ 
    session.SaveOrUpdate(entity); 
    session.Flush(); 
    session.CreateSQLQuery("EXEC foo").ExecuteUpdate(); 
    transaction.Commit(); 
    tsc.Complete(); 
} 

(FWIW - строго говоря, транзакция NHibernate здесь не нужна, так как вы действительно ничего не делаете с сеансом после Flush, но это хорошая практика использовать явную транзакцию NH в любом случае в случае изменения логики в будущем.)

Обратите внимание, что я предпочитаю использовать IStatelessSession экземпляров для любые вставки/обновления пакета/etc. - если вы используете обычные экземпляры ISession и вам нужно действительно получать обновления, сделанные ExecuteUpdate, вам, возможно, потребуется использовать методы сеанса Evict или Clear, чтобы гарантировать получение обновлений.

0

Я не уверен, какую версию NHibernate вы используете, но учитывая, что сейчас уже 2 года, скорее всего, ваш ответ применим к более ранней версии. Я использую 3.3.3.GA, и транзакции NHibernate смогли управлять SQL Query ExecuteUpdate без проблем. я проверил, что я не смог увидеть данные, полученные до тех пор, пока я не выполнил транзакцию. Commit().

using (var session = sessionFactory.OpenStatelessSession()) 
using (var transaction = session.BeginTransaction()) 
{ 
    session.SaveOrUpdate(entity); 
    session.Flush(); 
    session.CreateSQLQuery("EXEC foo").ExecuteUpdate(); 
    transaction.Commit(); 
} 
Смежные вопросы