简体   繁体   English

在Nhibernate中缺少对环境事务的支持吗?

[英]Missing support for ambient transactions in nhibernate?

I know NHibernate supports ambient transactions, because NHibernate sessions enlists in the ambient transactions while inside a transaction scope. 我知道NHibernate支持环境事务,因为NHibernate会话在事务范围内加入环境事务。 However, there are some oddities, consider the following test: 但是,存在一些奇怪之处,请考虑以下测试:

[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); 
    }
}

This test fails. 该测试失败。 How will NHibernate ensure that the ambient transaction is not persisted to the database? NHibernate如何确保环境事务不会持久化到数据库?

I know relatively well how Hibernate work with JTA in the Java world, but I am not a .NET expert. 我比较了解Hibernate在Java世界中如何与JTA一起工作,但是我不是.NET专家。 Your question nevertheless caught my attention. 但是您的问题引起了我的注意。

In Java, you need to configure Hibernate with either JDBC or JTA transaction. 在Java中,您需要使用JDBC或JTA事务配置Hibernate。 In which case, the Transaction object returned by Hibernate wraps either a transaction that is bound to one database connection (JDBC) or the global transaction that is thread-local. 在这种情况下,由Hibernate返回的Transaction对象将包装绑定到一个数据库连接(JDBC)的事务或包装在线程本地的全局事务。 The global thread-local transaction context can be invalidated using UserTransaction#setRollbackOnly , which ensures it will never commit succesfully. 可以使用UserTransaction#setRollbackOnly来使全局线程本地事务上下文无效,以确保它永远不会成功提交。 It's however preferable to not manage transaction through Hibernate but to use solely the UserTransaction object provided by JTA. 但是,最好不要通过Hibernate管理事务,而只使用JTA提供的UserTransaction对象。

This still seems to be the same in NHibernate and there is two transaction factories. 在NHibernate中似乎还是一样,并且有两个事务工厂。 One for distributed transactions and one for local transactions . 一种用于分布式事务 ,一种用于本地事务 But both return an AdoTransaction : 但是两者都返回AdoTransaction

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

This doesn't seem to be consistent in case of distributed / ambient transactions. 在分布式/环境事务中,这似乎不一致。 I don't see how rollback would work in this case given that the global transaction context can not be invalided in .NET (so far I understand), and AdoTransaction seems to represent a transaction on database connection. 鉴于无法在.NET AdoTransaction全局事务上下文无效(到目前为止,我知道),因此我看不到在这种情况下rollback将如何工作,并且AdoTransaction似乎代表了数据库连接上的事务。

So I feel like the answer to your question is "it won't" which would explain that your test fails. 因此,我觉得您的问题的答案是“不会”,这将说明您的测试失败。 This means that you should not manage transaction through NHiberate if you use ambient transaction. 这意味着,如果您使用环境事务,则不应通过NHiberate管理事务。 Just like it's not a recommended practice with Hibernate and JTA. 就像在Hibernate和JTA中不推荐这样做一样。

EDIT 编辑

See also this question: How does TransactionScope roll back transactions? 另请参阅以下问题: TransactionScope如何回滚事务?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM