如何在动态Linq查询中嵌套OrderBy

本文关键字:嵌套 OrderBy 查询 Linq 动态 | 更新日期: 2023-09-27 18:24:47

我使用的是Dynamic Linq,今天我想构建一个稍微复杂一点的嵌套查询:

"Composition
.Where(((ExpirationDate > DateTime.UtcNow.Date) && (ExpirationDate.Year != 9999)))
.OrderBy('"ExpirationDate ASC'")
.Select(ExpirationDate)
.FirstOrDefault() == @0"

(在这篇文章中,中断只是为了可读性,而不是在代码中)

查询由一个字符串变量保存,并传递给以下对象:

private static Func<IQueryable<T>, object, IQueryable<T>> CreateWhereExpression<T>(string whereClause) where T : class
{
     return (q, o) => q.Where(whereClause, o);
}

它愉快地创建了Where表达式。(请注意,whereClause包含"Composition.Where…"上方的确切字符串)但一旦到了执行的时候,它就会抱怨:

不存在适用的聚合方法"OrderBy"

所以我的问题是,我做错了什么?如何使嵌套的OrderBy工作?

如何在动态Linq查询中嵌套OrderBy

默认情况下,DynamicLinq支持对IEnumerable字段进行嵌套查询的一些函数,所有这些函数都是在接口IEnumerableSignatures中定义的,如WhereAnyCount等,但没有您需要的OrderbySelectFirstOrDefault
所以你可以像一样把它添加到这个界面上

interface IEnumerableSignatures
{
    ....
    void OrderBy(object selector);
    void Select(object selector);
    void FirstOrDefault();
}

之后,你需要修复像这个一样的ParseAggregate方法

Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
{
    ....
    if (signature.Name == "Min" || signature.Name == "Max" 
        || signature.Name == "OrderBy" || signature.Name == "Select" //add this for support OrderBy and Select that need two generic parameters
    )
    ....
}

最后下一个查询将是工作

"Composition
.Where((ExpirationDate > DateTime.UtcNow.Date) && (ExpirationDate.Year != 9999))
.OrderBy(ExpirationDate)
.Select(ExpirationDate)
.FirstOrDefault() == @0"