5

我正在尝试将 NHibernate 与未使用 NHibernate 映射的遗留实体一起使用。有时这意味着我需要手动将 NHibernate 数据刷新到数据库,这样当我尝试将遗留实体与 NHibernate 映射的实体连接时,我不会收到外键异常。

当这发生在需要回滚的事务中时,就会出现问题。从 NHibernate 刷新的数据不会回滚。

对此我能做些什么吗?

更新

仍然很好奇如何做到这一点 - 我不相信给出的任何一个答案都解决了这个问题。我需要调用 Flush()。问题是,如何回滚已刷新的数据?

4

3 回答 3

4

检查这个:强制执行查询而不刷新/提交

我似乎有同样的问题,我会刷新然后我会回滚,但一些数据会保留在数据库中。但是,我的代码中有一些部分会调用提交,并且无法回滚。将接受的答案的代码片段视为事务、刷新、回滚和提交的正确用法,并考虑到这种模式可以扩展......

在单个工作单元中(即,我们将 Web 应用程序中的请求视为单个工作单元,并且该请求中发生的所有事情都存在于提交 onEndRequest 的单个事务中):

  1. 您调用_sessionFactory.OpenSession(), _session.BeginTransaction(),_session.CommitTransaction()并且_session.CloseSession()只有一次。

  2. 您可以根据需要调用多次_session.Flush()_session.RollBackTransaction()但 Flush() 会在提交时自动调用。当您需要进行查询并确保获取的数据不会过时时,您可能需要调用 Flush。

  3. 请注意,一旦提交事务被提交,之后的所有操作都不会发生在该事务上。相反,NHibernate 将在后台创建必要的事务(http://www.nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions),此时您已经在跟踪一致性和可能的​​逻辑完整性时遇到了问题

  4. 如果您确实必须在工作单元中间调用 commit,强烈建议您在此时创建一​​个新事务,以便您可以显式管理它

  5. 更好的是尝试嵌套事务据称会允许部分提交;您可以回滚“根”事务,所有更改都将被还原。我还没有真正测试过 .NET 和 SQL Server 的这个特性,尽管数据库中的嵌套事务本身还有很多不足之处,而且我不知道 ADO.NET 如何准确地检测这个特性。

从 1.2 开始,所有版本的 NHibernate 都对第 1 点到第 4 点进行了测试。

于 2011-04-11T18:39:38.030 回答
3

为了格式化,我允许自己在这里更新 tolism7 的答案。

  1. 使用using并忘记 transaction.Dispose() -在 using 块的末尾transaction将自动被'd'。Dispose
  2. throw- 不要抛出 ex,因为这意味着丢弃你的堆栈跟踪(请参阅这篇文章,其中指出“当 .NET 框架执行此语句时:throw ex;它会丢弃当前函数上方的所有堆栈信息。”)

.

public void CommitChanges()
{
    using (var transaction = Session.BeginTransaction())  // <-- open scope
        try
        {
            // do something
            transaction.Commit();
        }
        catch (HibernateException)
        {
            transaction.Rollback();
            _session.Close();
            _session.Dispose();

            throw;  // <-- this way the stacktrace stays intact!
        }
}

可以在此处找到这段代码的VB.NET 版本

于 2010-07-13T12:14:47.530 回答
2

当使用 NHibernate 的事务时,尽量避免使用 Session.Flush() 而是使用它在内部调用 session.flush() 的 transaction.Commit()。

如果在 Commit() 期间发生错误并且需要回滚事务,则可以这样解决。

public static void CommitChanges()
{
    ITransaction transaction = Session.BeginTransaction();

    try
    {
        transaction.Commit();
    }
    catch (HibernateException ex)
    {
        transaction.Rollback();
        //close and dispose session here
        throw ex;
    }
    finally
    {
        transaction.Dispose();
    }
}

现在,如果手动调用 flush() 或调用 commit() 成功通过,则无法使用 NHibernate 机制回滚事务。特别是在调用 transaction.Commit() 命令时,NHibernate 创建的 AdoTransaction 会在 Commit() 完成后立即释放,因此您无法访问它以回滚。

上面的代码示例允许您捕获提交期间发生的错误,然后回滚已经开始的事务。

现在,不是在上面的示例中调用 transaction.Commit(),而是在我的测试中调用 session.Flush(),因为从未提交事务,所以没有数据保存在数据库中。

我不知道您的代码是什么样的,但是如果您以模式调用,如上面的代码示例所示,transaction.commit() 而不是 Session.Flush() 它应该为您提供一种实现您所想的方法想。

于 2009-11-19T11:45:41.523 回答