NHibernate ExecuteUpdate不参与当前事务?

时间:2012-05-15 02:27:16

标签: nhibernate transactions

我的代码如下:

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

令人惊讶的是,SQL查询在保存anObject之前执行。显然,ExecuteUpdate命令不参与当前事务。有没有办法让更新在事务中登记?

2 个答案:

答案 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所做的更新,那么您可能需要使用会话的EvictClear方法来保证获取更新。

答案 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();
}