1

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 はどのように保証しますか?

4

1 に答える 1

1

Java の世界で Hibernate が JTA とどのように連携するかは比較的よく知っていますが、.NET の専門家ではありません。それにもかかわらず、あなたの質問は私の注意を引きました。

Java では、JDBC または JTA トランザクションで Hibernate を構成する必要があります。その場合、TransactionHibernate によって返されるオブジェクトは、1 つのデータベース接続 (JDBC) にバインドされたトランザクション、またはスレッドローカルなグローバル トランザクションのいずれかをラップします。グローバル スレッドローカル トランザクション コンテキストは、 を使用して無効にすることができますUserTransaction#setRollbackOnly。これにより、コミットが成功しないことが保証されます。UserTransactionただし、Hibernate を介してトランザクションを管理するのではなく、JTA によって提供されるオブジェクトのみを使用することをお勧めします。

これは NHibernate でも同じようで、2 つのトランザクション ファクトリがあります。1 つは分散トランザクション用、もう 1 つはローカル トランザクション用です。しかし、どちらも次を返しますAdoTransaction

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

分散/アンビエント トランザクションの場合、これは一貫していないようです。rollbackグローバル トランザクション コンテキストを .NET で無効にすることができず (私が理解している限り)、AdoTransactionデータベース接続上のトランザクションを表しているように見えるため、この場合にどのように機能するかわかりません。

したがって、あなたの質問への答えは「そうではない」ということだと思います。これは、テストが失敗したことを説明します。これは、アンビエント トランザクションを使用する場合、NHiberate を介してトランザクションを管理するべきではないことを意味します。Hibernate と JTA で推奨される方法ではないのと同じように。

編集

この質問も参照してください: TransactionScope はトランザクションをどのようにロールバックしますか?

于 2010-02-02T12:53:02.647 に答える