【问题标题】:Dynamic OrderBy expression with bool predicate带有布尔谓词的动态 OrderBy 表达式
【发布时间】:2019-06-14 19:30:19
【问题描述】:

我有一个模型类

public class MyModel
{
    public long Id { get; set; }

    public string Name { get; set; }
}

我目前正在从数据库中返回MyModel 的有序列表(按名称):

return await Db.MyModel
    .AsNoTracking()
    .OrderBy(x => x.Name)

但是,数据库中的一个值是“N/A”,我希望通过一些选择器进行排序,同时最后留下“N/A”,所以基本上:

 return await Db.MyModel
    .AsNoTracking()
    .OrderBy(x => x.Name == "N/A)
    .ThenBy(x => x.Name)

我创建了一个 IQueryable 扩展,但在 Expression.Call(...) 上出现错误

InvalidOperationException:类型“System.Linq.Queryable”上没有通用方法“OrderBy”与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。

public static IQueryable<TSource> OrderNALast<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> selector)
{
    var expression = source.Expression;
    var parameter = Expression.Parameter(typeof(TSource), "x");

    var left = (MemberExpression)selector.Body;
    var right = Expression.Constant("N/A");
    var predicateBody = Expression.Equal(left, right);

    var lambda = Expression.Lambda<Func<TSource, bool>>(predicateBody, parameter);

    expression = Expression.Call(
        typeof(Queryable), 
        "OrderBy",
        new[] { source.ElementType, left.Type },
        expression,
        lambda);

    var appendedQuery = (IOrderedQueryable<TSource>)source.Provider.CreateQuery<TSource>(expression);
    return appendedQuery.ThenBy(selector);
}

【问题讨论】:

  • 这个方法有你使用的重载吗? docs.microsoft.com/en-us/dotnet/api/… 我似乎找不到 Expression.Call(Type, string, Type[], Expression, Expression)
  • @iSpain17 我正在使用public static MethodCallExpression Call(Type type, string methodName, Type[] typeArguments, params Expression[] arguments);

标签: c# lambda


【解决方案1】:

哦,我想我看到了问题。

在 Expression.Call 中,第三个参数需要调用静态方法的泛型类型参数。

Queryable.OrderBy() 有两个重载:

public static System.Linq.IOrderedQueryable<TSource> OrderBy<TSource,TKey> (this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<Func<TSource,TKey>> keySelector, System.Collections.Generic.IComparer<TKey> comparer);

public static System.Linq.IOrderedQueryable<TSource> OrderBy<TSource,TKey> (this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<Func<TSource,TKey>> keySelector);

但不是给予

TSourcebool

作为参数,你给它

TSourcestring

作为参数。

应该是这样的:

expression = Expression.Call(
        typeof(Queryable), 
        "OrderBy",
        new[] { typeof(TSource), typeof(bool) },
        expression,
        lambda);

(或者你也可以使用 source.ElementType 作为第一种类型。)

【讨论】:

  • 您的意思是应该typeof(TSource)source.GetType()?但它们都不起作用。
  • source.GetType(),是的,对不起。它给出了什么错误?
  • 你不能在变量上使用typeof()
  • 我很困惑对不起:D
  • 所以你的帖子实际上让我知道这一切是如何联系在一起的,我确实找出了问题所在 - 类型参数需要与 func 中的相同,因此 &lt;TSource, bool&gt;,我是给它&lt;TSource, string&gt;,所以答案是给new[] { typeof(TSource), typeof(bool) },
猜你喜欢
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-13
相关资源
最近更新 更多