在表达式中添加 HasValue 后动态 linq OrderBy() 失败

Dynamic linq OrderBy() failing after adding HasValue in the expression

我已经按照 this link 使用表达式树在 linq 查询中创建动态 orderby 子句。

但后来我遇到了一个场景,我必须在对列的值进行排序时记住空值,因为我的数据库列允许空值 即所有非空值应按升序排序,然后应遵循空值。

所以我按照 this link 修改了我的动态 LINQ 代码来处理上述情况。即我试图在我的 OrderBy() 调用中添加 HasValue 调用。但它开始失败并出现以下错误。

No generic method 'OrderBy' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

导致Expression.Call()失败的参数:

p.IsProcessStarted.HasValue

下面是我使用的代码:

public static class ExtensionMethods
{
   public static IQueryable<TEntity> OrderBy<TEntity>(
     this IQueryable<TEntity> source, string orderByProperty, bool desc)
   {
     string command = desc ? "OrderByDescending" : "OrderBy";
     var type = typeof(TEntity);
     var property = type.GetProperty(orderByProperty);
     var propertyType = property.PropertyType;
     bool isNullable = propertyType.IsGenericType
         && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>);

     var parameter 
       = Expression.Parameter(type, "p");
     MemberExpression propertyAccess
       = Expression.MakeMemberAccess(parameter, property);
     MemberExpression hasValue 
       = Expression.Property(propertyAccess, "HasValue");            
     LambdaExpression orderByExpression
       = Expression.Lambda(hasValue, parameter);
     MethodCallExpression resultExpression
       = Expression.Call(typeof(Queryable), command, 
         new Type[] { type, property.PropertyType }, source.Expression,
         Expression.Quote(orderByExpression));

     return source.Provider.CreateQuery<TEntity>(resultExpression);
   }
}

我是这样调用上面的扩展方法的:

var res = myQuery.OrderBy("IsProcessStarted", true)

而我要构建的表达式是 .OrderBy(p>=p.IsProcessStarted.HasValue)

您的代码正在尝试实现此 OrderBy:

.OrderBy(p => p.HasValue)

这个表达式returns一个bool。因此,要使其正常工作,您必须在 Expression.Call 调用中正确指定类型,如下所示:

MethodCallExpression resultExpression
    = Expression.Call(typeof(Queryable), command,
    new Type[] { type, typeof(bool) }, // Expression<Func<type, bool>>
    source.Expression,
    Expression.Quote(orderByExpression));

注意:我不知道这是否是您想要的,但是如果您这样实现,代码可以正确编译和运行。但是,正如我在评论中所问的那样,您应该显示要实施的 lambda。您还应该修改您的代码以支持可为 null 和不可为 null 的属性的情况。您正在使用 isNullable 检查它,但您没有在任何地方使用它