我的代码如下:
using (var session = this.sessionCreator.OpenSession())
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(anObject);
session.CreateSQLQuery(sql)
.ExecuteUpdate();
transaction.Commit();
}
令人惊讶的是,SQL查询在保存anObject
之前执行。显然,ExecuteUpdate
命令不参与当前事务。有没有办法让更新在事务中登记?
答案 0 :(得分: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
个实例用于任何批量插入/更新/等。 - 如果您使用常规ISession
个实例并且需要实际检索ExecuteUpdate
所做的更新,那么您可能需要使用会话的Evict
或Clear
方法来保证获取更新。
答案 1 :(得分:0)
我不确定您使用的是什么版本的NHibernate,但鉴于它现在是2年后,很可能您的答案适用于早期版本。我正在使用3.3.3.GA和NHibernate事务能够毫无问题地管理SQL查询ExecuteUpdate。我检查了在运行transaction.Commit()之后我才能看到提交的数据。
using (var session = sessionFactory.OpenStatelessSession())
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(entity);
session.Flush();
session.CreateSQLQuery("EXEC foo").ExecuteUpdate();
transaction.Commit();
}