In NHibernate 3.0, FlushMode.Auto does not work when running under an ambient transaction only (that is, without starting an NHibernate transaction). Should it?
using (TransactionScope scope = new TransactionScope()) 
{
    ISession session = sessionFactory.OpenSession();
    MappedEntity entity = new MappedEntity() { Name = "Entity", Value = 20 };
    session.Save(entity);
    entity.Value = 30;
    session.SaveOrUpdate(entity);
    // This returns one entity, when it should return none
    var list = session.
               CreateQuery("from MappedEntity where Value = 20").
               List<MappedEntity>();
}
(Example shamelessly stolen from this related question)
In the NHibernate source I can see that's it's checking whether there's a transaction in progress (in SessionImpl.AutoFlushIfRequired), but the relevant method ( SessionImpl.TransactionInProgress) does not consider ambient transactions - unlike its cousin ConnectionManager.IsInActiveTransaction, which does consider ambient transactions.
Good news. Thanks to Jeff Sternal (who nicely identified the problem) I updated https://nhibernate.jira.com/browse/NH-3583 and thanks to the NH staff, there's already a fix and a pull request so in the upcoming release 4.1.x.x this ISSUE will be fixed.
You should use an explicit NHibernate transaction always.
using (TransactionScope scope = new TransactionScope()) 
using (ISession session = sessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
    //Do work here
    transaction.Commit();
    scope.Complete();
}
I see you also wrote in the NH dev list - while this can change in the future, that's how it works now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With