4

I have code that looks like this:

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

Surprisingly, the SQL query executes before anObject is saved. Apparently, the ExecuteUpdate command does not participate in the current transaction. Is there any way to get the update to enlist in the transaction?

4

2 回答 2

5

NHibernate 事务与 DB 事务不同;框架无法知道您ExecuteUpdate正在影响哪些实体或哪些数据,因此不会自动刷新SaveOrUpdate(可能会根据会话的延迟FlushMode)和CreateSQLQuery(如果您使用,则始终是即时的)之间的会话ExecuteUpdate

一般来说,如果您将 NHibernate 逻辑与较低级别的 SQL 逻辑(存储过程等)结合起来,那么您将需要使用 aTransactionScope来保证原子性:

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方法来保证获取更新。

于 2012-05-18T18:12:28.960 回答
0

我不确定您使用的是哪个版本的 NHibernate,但鉴于现在是 2 年后,您的答案很可能适用于早期版本。我正在使用 3.3.3.GA 并且 NHibernate 事务能够毫无问题地管理 SQL Query 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();
}
于 2014-12-12T21:47:38.023 回答