NHibernate 3.0:TransactionScope和Auto-Flushing

时间:2011-03-03 23:19:16

标签: nhibernate transactionscope flush distributed-transactions nhibernate-3

在NHibernate 3.0中,FlushMode.Auto仅在环境事务下运行时无效(即,无需启动NHibernate事务)。应该吗?

using (TransactionScope scope = new TransactionScope()) 
{
    ISession session = sessionFactory.OpenSession();
    MappedEntity entity = new MappedEntity() { Name = "Entity", Value = 20 };
    session.Save(entity);

    entity.Value = 30;
    session.SaveOrUpdate(entity);

    // This returns one entity, when it should return none
    var list = session.
               CreateQuery("from MappedEntity where Value = 20").
               List<MappedEntity>();
}

(从this related question无耻地偷走的例子)

在NHibernate源代码中,我可以看到它正在检查是否有正在进行的事务(在SessionImpl.AutoFlushIfRequired中),但相关方法(SessionImpl.TransactionInProgress)不考虑环境事务 - 与其表兄{{不同} 1}},确实考虑环境事务。

5 个答案:

答案 0 :(得分:5)

好消息。感谢Jeff Sternal(他很好地确定了问题)我更新了https://nhibernate.jira.com/browse/NH-3583并感谢NH工作人员,已经有了修复和拉取请求所以在即将发布的4.1.xx版本中,此问题将得到修复。

答案 1 :(得分:3)

您应该始终使用显式的NHibernate事务。

using (TransactionScope scope = new TransactionScope()) 
using (ISession session = sessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
    //Do work here
    transaction.Commit();
    scope.Complete();
}

我看到你也在NH开发列表中写道 - 虽然这可能会在未来发生变化,但现在它的工作方式也是如此。

答案 2 :(得分:2)

Diego提供的答案在您拥有oracle数据库的情况下不起作用。 (releated question)。 session.BeginTransaction将失败,因为连接已经是事务的一部分。

看起来我们必须在我们的应用程序(WCF,NHibernate,Oracle)中围绕这个问题编写一些代码,但它只是感觉就像NHibernate应该提供的开箱即用的东西。 所以,如果有人有一个好的答案,那将非常感激。

答案 3 :(得分:1)

我为甲骨文找到了答案。请在此处查看:NHibernate TransactionScope issue with Oracle 11g

答案 4 :(得分:0)

对我来说,我不知道背后的原因,但是在会话处理之前强制会话刷新似乎对我有用。例如 使用(会话) { //做你的工作

调用Session.flush(); }

我确认这适用于我的分布式事务,因为如果不这样做,我会在处理TransactionScope时得到“事务已中止”。

甚至将session.FlushMode设置为Commit也不适用于我。