Search code examples
nhibernatetransactionslinq-to-nhibernatenhprof

NHibernate Linq uses implicit transaction?


I'm using Ayende's NHibernate Linq version 2.1.2, available here, and when I use NHProf to inspect queries that use this method:

public IQueryable<T> GetAll()
{
    return Session.Linq<T>();
}

It gives me the warning that I'm using an implicit transaction. Problem is, I'm using this in a repository to abstract out the database session, but I still want the flexibility of returning an IQueryable so I can run any Linq query I want. Is there a way to explicitly wrap the Session.Linq<T>() in a transaction without exposing it, or should I just ignore the warning in this case?

A little more background. I'm using the method like so:

var repo = new Repository();
var animals = repo.GetAll<Animal>().Where(x => x.Size > 100);
NoahsArk.LargeAnimals.AddRange(animals);

Solution

  • I had a very similar problem which I solved quite simply.

    I created a LinqClass within my repository returned by my Linq method

    public virtual LinqClass Linq()
    {
        return new LinqClass(Session, LinqSource());
    }
    
    public class LinqClass : IDisposable
    {
        public LinqClass(ISession session, IQueryable<T> linqSource)
        {
            _linq = linqSource;
            _transaction = session.BeginTransaction();
        }
        private readonly IQueryable<T> _linq;
        private readonly ITransaction _transaction;
    
        public IQueryable<T> Linq
        {
            get { return _linq; }
        }
    
        public void  Dispose()
        {
             _transaction.Commit();
        }
    }
    

    I could then wrap my linq statements up in a using block

        using (var linq = Linq())
        {
            var versions = from t in linq.Linq
                           where t.BaseName == BaseName
                           orderby t.Version descending
                           select t.Version;
    
            return versions.Take(1).SingleOrDefault();
        }
    

    and even if returning data from the middle of it, the transaction commit is still called. No more implicit transactions. Obviously this example is for NHibernate, but it should work similarly for other things.