我正在尝试将NHibernate与未与NHibernate映射的遗留实体一起使用。有时这意味着我需要手动将NHibernate数据刷新到数据库,这样当我尝试将遗留实体与NHibernate映射实体连接时,我就不会收到外键异常。
当在需要回滚的事务中发生此问题时会发生问题。从NHibernate刷新的数据不会回滚。
我能做些什么吗?
更新
仍然很好奇如何做到这一点 - 我不相信给出的任何答案都能解决这个问题。我需要调用Flush()。问题是,如何回滚已刷新的数据?
答案 0 :(得分:4)
检查一下:Force query execution without flush/commit
我似乎有同样的问题,我会刷新然后我会回滚,但一些数据将保持在数据库中。但是,我的代码中有一些部分会调用一个无法回滚的提交。将接受的答案的代码片段视为事务,刷新,回滚和提交的正确用法,并考虑到可以扩展此模式......
在单个工作单元中(即我们将Web应用程序中的请求视为单个工作单元,并且该请求中发生的所有事情都存在于提交onEndRequest的单个事务中):
您只需拨打一次_sessionFactory.OpenSession()
,_session.BeginTransaction()
,_session.CommitTransaction()
和_session.CloseSession()
。
您可以根据需要多次调用_session.Flush()
和_session.RollBackTransaction()
,但会自动在提交时自动调用Flush()。当您需要进行查询并确保所提取的数据不会过时时,您可能需要调用Flush。
请注意,提交事务一旦提交,之后的所有操作都不会发生在该事务上。相反,NHibernate将在幕后创建必要的事务(http://www.nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions) 您已经在跟踪一致性和可能的逻辑完整性方面遇到了问题
如果你真的必须在工作单元中间调用commit,强烈建议在那时创建一个新的事务,以便你可以明确地管理它
更好的是尝试嵌套交易,据称允许部分提交;您可以回滚“root”事务,所有更改都将被还原。我还没有真正测试过.NET和SQL Server的这个功能,虽然数据库中的嵌套事务本身还有很多不足之处,我不知道ADO.NET究竟如何支持这个功能。
从1。1开始,所有版本的NHibernate都测试了1到4点。
答案 1 :(得分:3)
为了格式化,我允许自己在这里更新tolism7的答案。
using
并忘记transaction.Dispose() - transaction
将在使用块的末尾自动为Dispose
d。throw
- 不要抛出ex,因为这意味着丢弃你的堆栈跟踪(请参阅this post其中所说的“当.NET Framework执行此语句时: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 version这段代码的here。
答案 2 :(得分: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()它应该给你一个方法实现你想要的。