2010-01-17 6 views
1

Je sais que NHibernate prend en charge les transactions ambiantes, car les sessions NHibernate s'enrôlent dans les transactions ambiantes à l'intérieur d'une portée de transaction. Cependant, il y a quelques bizarreries, considérez le test suivant:Support manquant pour les transactions ambiantes dans 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); 
    } 
} 

Ce test échoue. Comment NHibernate s'assurera-t-elle que la transaction ambiante n'est pas conservée dans la base de données?

Répondre

1

Je sais relativement bien comment Hibernate fonctionne avec JTA dans le monde Java, mais je ne suis pas un expert .NET. Votre question a néanmoins attiré mon attention.

En Java, vous devez configurer Hibernate avec une transaction JDBC ou JTA. Dans ce cas, l'objet Transaction renvoyé par Hibernate encapsule une transaction liée à une connexion de base de données (JDBC) ou la transaction globale qui est locale au thread. Le contexte de transaction locale thread-local peut être invalidé en utilisant UserTransaction#setRollbackOnly, ce qui garantit qu'il ne sera jamais commise avec succès. Il est cependant préférable de ne pas gérer les transactions via Hibernate mais d'utiliser uniquement l'objet UserTransaction fourni par JTA.

Cela semble toujours être le même dans NHibernate et il y a deux usines de transaction. Un pour distributed transactions et un pour local transactions. Mais à la fois un retour AdoTransaction:

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

Cela ne semble pas être compatible dans le cas des transactions distribuées/ambiantes. Je ne vois pas comment rollback fonctionnerait dans ce cas étant donné que le contexte de transaction globale ne peut pas être invalidé dans .NET (jusqu'à présent je comprends), et AdoTransaction semble représenter une transaction sur la connexion à la base de données.

Donc, je pense que la réponse à votre question est "ce ne sera pas" ce qui expliquerait que votre test échoue. Cela signifie que vous ne devez pas gérer les transactions via NHiberate si vous utilisez une transaction ambiante. Tout comme ce n'est pas une pratique recommandée avec Hibernate et JTA.

EDIT

Voir aussi cette question: How does TransactionScope roll back transactions?

Questions connexes