Generic query with NHibernate with eager loading

In my previous post, I showed how we could create generic methods to perform query, https://csharptipstricks.blogspot.com/2019/12/usage-of-expression-to-create-generic.html. However, the methods present there does not allow eager loading. In case you are wondering how eager loading is performed, see below. Do know that there are ways to assign eager loading during mapping, but I will not show it in this post.

Method I:
SessionFactory.OpenSession().Query<MyEntity>().Fetch(x => x.Property1).Fetch(x => x.Property2).ToList();

Method II:
var tempMyEntityQuery = GetSession().Query<MyEntity>().Fetch(x => x.Property1).ToFuture();
GetSession().Query<MyEntity>().Fetch(x => x.Property2).ToFuture();

List<MyEntity> myEntityList = tempMyEntityQuery .ToList();

Both the methods above will eager load Property1 & Property2 in a single trip to the database. However, I would choose method I because a single statement (with left outer join) is generated, instead of 2 statements in method II.

Now, if I want to incorporate eager query into my generic query, how could I do it? Firstly, let's try creating a static method which would execute method I.

public static INhFetchRequest<T, object> AddEagerLoadingItems<T>(IQueryable<T> iqueryable, params Expression<Func<T, object>>[] expressions)
{
    INhFetchRequest<T, object> test = iqueryable.Fetch(expressions[0]);

    for(int x = 1; x < expressions.Length; x++)
    {
        test = test.Fetch(expressions[x]);
    }

    return test;
}

The static method is basically attaching Fetch to our base query, the base query could be something like GetSession().Query<T>(). Next, let's create a client function for this helper method. Imagine that I would want a generic method to query a list of objects (let's just keep it simple and assume that I want everything), with eager loading of course, I could do something as follow,

public async Task<List<T>> GetDbRecordsList<T>(params Expression<Func<T, object>>[] expressions)
{
    if (expressions.Length > 0)
    {
        var withFetch = Helper.AddEagerLoadingItems(GetSession().Query<T>(), expressions);
        return await withFetch.ToListAsync();
    }
    else
    {
        return await GetSession().Query<T>().ToListAsync();
    }
}

Simple, right? We could further simplify the code above, but you get the gist of it.

Comments

Popular posts from this blog

ASP.NET Core service locator pattern

Ways to perform eager loading via NHibernate

Caching and generic query using NHibernate [.NET Core]