Ambient Transactions and NHibernate

About two weeks ago we had some discussions in the german Alt.NET mailing list whether ambient transactions can be used in combination with NHibernate, especially regarding performance implications of such an approach. Background of that discussion was that my colleague Sergey and I wanted to implement the repository pattern based on Linq 2 NHibernate in a way that exposes no NHibernate dependency to a surrounding layer. Besides that we didn’t want to dublicate the UnitOfWork pattern that NHibernate implements internally. Because of that we decided to try out ambient transactions (System.Transactions) as our UnitOfWork. Sergey has already posted about the design we’re currently investigating, so I won’t go into detail about that here. You can read more here:

We started with a simple test comparison between the behavior of NHibernates native ITransactions and NHibernate using TransactionScope for transactions. What we noticed :

FlushMode.Commit doesn’t work when using ambient Transactions

The following (xUnit) test fails:

1
2
3
4
5
6
7
8
9
10
11
[Fact]
public void Session_should_be_clean_after_commited_transaction()
{
  using (var tx = new TransactionScope())
  {
      SaveTwoPatients();
      tx.Complete();
  }

  Session.IsDirty().ShouldBeFalse();
}

But this can be easily fixed like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Fact]
public void Session_should_be_clean_after_commited_transaction_Fixed()
{
  using (var tx = new TransactionScope())
  {
          Transaction.Current.TransactionCompleted += (s, e) =>
          {
              if (e.Transaction.TransactionInformation.Status == TransactionStatus.Committed)
              {
                  Session.Flush();
                  Session.Clear();
              }
          };
          
          SaveTwoPatients();
          tx.Complete();
  }
  
  Session.IsDirty().ShouldBeFalse(); }

For some reason ambient Transaction are FASTER than NHibernates native counter parts

We have also some tests that perform a transactional insert a 1000 times. The duration of those tests are quite surprising. Have a look:

NHibernateTransactions

This has nothing to do with jitting in the CLR or the order how test are executed. I double checked the durations and ran each test on his own. I didn’t expect that gap, but I’m also not a NHibernate pro. Any thoughts? I’ll write more about our experiences with that approach soon. Our concept looks good on paper and our first impressions are not disproving either, so stay tuned …

Comments