【问题标题】:Reflection with IQueryable使用 IQueryable 进行反射
【发布时间】:2023-03-06 08:11:02
【问题描述】:

我正在尝试为 IQueryable 创建一个扩展方法,该方法通过对象的任意属性对其进行排序。

public static class IQueryableExtender

{

public static IQueryable<TSource> Sort<TSource>(this IQueryable<TSource> query, string orderProperty, string sortDirection = "asc")      
{

    var elementType = query.ElementType;

    var propertyInfo = elementType.GetProperty(orderProperty);
    if (propertyInfo == null)
    {
         throw new ArgumentException(string.Format("{0} is not a property on {1}", orderProperty, elementType.Name));
    }


    switch (sortDirection.ToLower())
    {
       case "asc":
       case "ascending":
           return query.OrderBy(x => propertyInfo.GetValue(x, null));
           break;
       case "desc":
       case "descending":
           return query.OrderByDescending(x => propertyInfo.GetValue(x, null));
           break;
    }

    return query;
}
}

调用该方法时出现此错误。我想这与 IQueryable 尚未执行和检索任何对象有关。

LINQ to Entities 无法识别方法System.Object GetValue(System.Object, System.Object[]),并且该方法无法转换为存储表达式。

我可以通过在 IQueryable 上执行 ToList 来解决它,但随后我在扩展方法中检索数据,这不是我想要的。

这可以解决吗?

【问题讨论】:

    标签: reflection iqueryable propertyinfo


    【解决方案1】:

    当您对 IQueryable 执行 LINQ 操作时,LINQ to Entities 会尝试在数据库中运行您的查询。在您的case "asc" 中,您执行 query.OrderBy,LINQ to Entities 将其解释为“将其转换为 SQL”,并且由于您使用反射调用而失败,它不知道如何将其转换为 SQL。

    你可以做 query.AsEnumerable().OrderBy(...)。这样做的一个效果是,随着 OrderBy 操作开始运行,查询的其余部分将按顺序执行以提供数据。

    您可以简单地使用 OrderBy 和 OrderByDescending 方法,而不是使用这些反射技巧,这些方法旨在采用委托来提取排序值。 (items.OrderBy(item =&gt; item.Property))。您缺少的是在同一方法中指定升序或降序的能力,但我会简单地执行以下一对方法:

    public static IOrderedQueryable<TSource> OrderByAscDesc<TSource, TKey>(
        this IQueryable<TSource> source,
        Expression<Func<TSource, TKey>> keySelector, bool isAsc
    ) {
        return (isAsc ? source.OrderBy(keySelector) : source.OrderByDescending(keySelector);
    }
    
    public static IOrderedQueryable<TSource> OrderByAscDesc<TSource, TKey>(
        this IQueryable<TSource> source,
        Func<TSource, TKey> keySelector, bool ascDesc
    ) {
        return (isDesc ? source.OrderBy(keySelector) : source.OrderByDescending(keySelector);
    }
    

    【讨论】:

    • 感谢您的回答。这不是我要找的。我忽略了我正在使用 MVC 并从视图中获取要排序的属性的名称。所以我想要一种方法,我可以只获取参数并反映对象的属性值并对其进行排序。这意味着我不需要任何 if 语句来选择与 if 语句一起使用的属性。
    • 这更有意义。在使用 OrderBy 之前添加 AsEnumerable() 应该可以解决它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 2012-01-13
    • 2011-07-13
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    相关资源
    最近更新 更多