开发者

NHibernate Linq uses implicit transaction?

开发者 https://www.devze.com 2022-12-14 06:53 出处:网络
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:

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开发者_如何学JAVA 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);


NHProf's message is actually not related to your repository implementation. It's just pointing out that you are running your query outside a transaction, which can be a source of problems.

Ayende explains this in a blog post: NH Prof Alerts: Use of implicit transactions is discouraged

You should manage your transactions from a higher level in your application. There are several ways to do this while using repositories, have a look at unhaddins


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.


I'm pretty sure you can ingnore this warning.

Can you see the transaction in NHProf?

http://groups.google.com/group/nhprof/browse_thread/thread/fbc97d3286ad783b

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号