Accepted answer

You have two problems with your approach. First is that you can't use a null propagating operator in Linq Expressions. Test this code:

var account = new Account();
// will cause "error CS8072: An expression tree lambda may not contain a null propagating operator"    
Expression<Func<string>> accountNumber = () => account?.AccountNumber;

Second and main problem is that your AccountNumber will be compiled into get_AccountNumber method and you can't invoke arbitrary methods with Linq to SQL. You may test this code:

public class AssetFileRecord
  public string AccountNumber => Account != null ? Account.AccountNumber : null;

while this can be compiled, it produce same runtime exception.

One possible way to workaround this problem is to create a map with expressions for complex properties:

var map = new Dictionary<string, Expression>
        "AssetFileRecord.AccountNumber", // type and property
        (Expression<Func<AssetFileRecord, string>>) (
            afr => afr.Account != null ? afr.Account.AccountNumber : null

Now you can rewrite your method that builds dynamic OrderBy with respect to this map:

private static IQueryable<T> DynamicOrderBy<T>(
    IQueryable<T> source,
    string sortProperty,
    Dictionary<string, Expression> map)
    var type = typeof(T);
    var parameter = Expression.Parameter(type, "p");
    var property = type.GetProperty(sortProperty, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

    Expression whereLambda;
    if (!map.TryGetValue($"{type.Name}.{sortProperty}", out whereLambda))
        var propertyAccess = Expression.MakeMemberAccess(parameter, property);
        whereLambda = Expression.Lambda(propertyAccess, parameter);
    // else we just using a lambda from map

    // call OrderBy
    var query = Expression.Call(
        new[] {type, property.PropertyType},

    return source.Provider.CreateQuery<T>(query);

Related Articles