简体   繁体   中英

Dynamic sorting in NHibernate QueryOver using expressions

Given the following QueryOver :

UserProfile userProfileAlias = null;
Pegfile pegfileAlias = null;
var q = Session.QueryOver(() => pegfileAlias)
        .JoinAlias(() => pegfileAlias.UserProfile, () => userProfileAlias);

I would like to make the following statement dynamic, by swapping

q = q.OrderBy(() => userProfileAlias.Forename).Asc;

(OrderBy(Expression<Func<object>> or ( OrderBy(Expression<Func<T, object>>) )

with

q = q.OrderBy(GetMemberExpression(userProfileAlias, "Forename")).Asc;

I borrowed from another post to get

private Expression<Func<object>> GetMemberExpression(UserProfile instance, string propertyName)
        {
            var arg = Expression.Constant(instance, typeof(UserProfile));
            var body = Expression.Convert(Expression.PropertyOrField(arg, propertyName), typeof(UserProfile));
            var lambda = Expression.Lambda<Func<object>>(body);
            return lambda;
        }

but this isn't working, i get:

System.InvalidOperationException
No coercion operator is defined between types 'System.String' and 'Pegfect.Domain.PegDudes.UserProfile'.

i think I probably need to match the following sig:

OrderBy(Expression<Func<UserProfile,object>>)

how to turn GetMemberExpression into returning that?

The reason why your version doesn't work is the fact that NHibernate doesn't actually assign a value to the variable used as an alias in JoinAlias . It is merely a token that is being parsed. This means that it needs to be the exact same variable , when you want to use it elsewhere.
To achieve this, you need to save the alias expression and use its body to retrieve that variable:

UserProfile alias = null;
Expression<Func<object>> aliasExpression = () => alias;
session.QueryOver<Pegfile>()
       .JoinAlias(x => x.UserProfiles, aliasExpression)
       .OrderBy(GetMemberExpression(aliasExpression, "Forename")).Asc
       .List();

private Expression<Func<object>> GetMemberExpression(
                                     Expression<Func<object>> aliasExpression,
                                     string property)
{
    var propertyExpression = Expression.Property(aliasExpression.Body,
                                                 typeof(UserProfile), property);
    var body = Expression.Convert(propertyExpression, typeof(object));

    var result = Expression.Lambda<Func<object>>(body);
    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM