2010-01-17 49 views
1

我知道NHibernate支持环境事务,因为NHibernate会话在事务范围内的环境事务中使用。但是,有一些奇怪的是,考虑以下测试:缺少对nhibernate中环境事务的支持?

[Test] 
public void Transaction_RollsBackTransactionInsideOfAmbientTransaction_AmbientTransactionAborted() 
{ 
    // arrange 
    ISessionFactory sessionFactory = SessionFactoryOneTimeInitializer.GetTestSessionFactory(); 
    ISession session = sessionFactory.OpenSession(); 
    SessionFactoryOneTimeInitializer.CreateDataBaseSchemaIfRequiredByConfiguration(session); 

    using (new TransactionScope()) 
    { 
     using (ITransaction transaction = session.BeginTransaction()) 
     { 
      // act 
      transaction.Rollback(); 
     } 

     // assert 
     Assert.AreEqual(TransactionStatus.Aborted, Transaction.Current.TransactionInformation.Status); 
    } 
} 

该测试失败。 NHibernate将如何确保环境事务不会持久化到数据库?

回答

1

我比较了解Hibernate如何在Java世界中使用JTA,但我不是.NET专家。不过你的问题引起了我的注意。

在Java中,您需要使用JDBC或JTA事务来配置Hibernate。在这种情况下,Hibernate返回的Transaction对象会封装绑定到一个数据库连接(JDBC)的事务或线程本地的全局事务。使用UserTransaction#setRollbackOnly可以使全局线程本地事务上下文无效,从而确保它永远不会成功提交。然而,最好不要通过Hibernate来管理事务,而是仅使用JTA提供的对象UserTransaction

这在NHibernate中似乎还是一样,并且有两个事务工厂。一个用于distributed transactions,另一个用于local transactions。但无论返回AdoTransaction

public ITransaction CreateTransaction(ISessionImplementor session) 
{ 
    return new AdoTransaction(session); 
} 

这似乎并不在分布式/环境事务的情形相一致。我没有看到rollback在这种情况下如何工作,因为全局事务上下文无法在.NET中无效(迄今为止我了解),并且AdoTransaction似乎代表数据库连接上的事务。

所以我觉得你的问题的答案是“它不会”,这将解释你的测试失败。这意味着如果您使用环境交易,则不应通过NHiberate管理交易。就像这不是Hibernate和JTA推荐的做法。

编辑

另见这个问题:How does TransactionScope roll back transactions?