Vincent
Vincent

Reputation: 1477

How does nesting an OrderBy in a Dynamic Linq query work?

I'm using Dynamic Linq and today I wanted to build a slightly more complex nested query:

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

(the breaks are only there for readability in this post, not really there in code)

The query is held by a string variable and passed to this:

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

Which happily creates the Where expression. (note that whereClause contains the exact string above "Composition.Where....") But as soon as it's time to execute, it will complain:

No applicable aggregate method 'OrderBy' exists

So my question is, what am I doing wrong? How can I get the nested OrderBy to work?

Upvotes: 3

Views: 751

Answers (1)

Grundy
Grundy

Reputation: 13381

By default DynamicLinq support a little functions for nested query to IEnumerable fields, all it defined in inteface IEnumerableSignatures like Where, Any, Count and etc, but don't have Orderby, Select or FirstOrDefault what you need.
So you can add it to this interface like

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

after that you need fix ParseAggregate method like this

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
    )
    ....
}

at last next query will be work

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

Upvotes: 3

Related Questions