1

hello i follow the guide in https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/how-to-use-expression-trees-to-build-dynamic-queries to create filter and sorting in my relation class, i need to filter and sort using the children column "Channel"

this is my base class

public class MeterTransaction : EviModelBase
{        
    public int TariffDuration { get; set; }
    public decimal? TariffPackageKwh { get; set; }
    public decimal? TariffPackagePrice { get; set; }
    public decimal? TariffRatePerKwh { get; set; }
    public decimal? TariffRateMinFee { get; set; }

    // Meter CreditBalance after transaction
    public decimal CreditBalance { get; set; }
    public DateTimeOffset? CreditExpiration { get; set; }
    [Timestamp]
    public byte[] RowVersion { get; set; }
    public Meter Meter { get; set; }
}

and this is the Meter Class

public class Meter : EviModelBase
{
    public MeterVendor Vendor { get; set; }
    public string Model { get; set; }
    public string SerialNumber { get; set; }
    public string Channel { get; set; }

}

this is the code to filter and sort the data :

public static IQueryable<T> OrderByNew<T>(this IQueryable<T> source, SortModel sortModel)
            {
                    ParameterExpression p = Expression.Parameter(typeof(T), "p");

                    // Construct the nested properties
                    string[] nestedProps = sortModel.ColId.Split('.');
                    Expression mbr = p;
                    for (int i = 0; i < nestedProps.Length; i++)
                            mbr = Expression.PropertyOrField(mbr, nestedProps[i]);

                    LambdaExpression pred = Expression.Lambda(
                            Expression.Equal(
                                    mbr,
                                    Expression.Constant("EVI0000101")
                                    ),
                                    p
                    );

                    var method = string.Equals(sortModel.Sort, "desc", StringComparison.OrdinalIgnoreCase) ?
                            "OrderByDescending" :
                            "OrderBy";
                    var whereCallExpression = Expression.Call(typeof(Queryable), "where", new Type[] { source.ElementType }, source.Expression, pred);
                    var orderByExpression = Expression.Lambda(mbr, p);

                    MethodCallExpression orderByCallExpression = Expression.Call(
                            typeof(Queryable),
                            method,
                            new Type[] { source.ElementType},
                            whereCallExpression,
                            Expression.Quote(orderByExpression));
                    // ***** End OrderBy *****

                    return source.Provider.CreateQuery<T>(orderByCallExpression);
            }
    }

Actually the "whereCallExpression" is working fined and filtering the data that i want without error, but the sorting logic give an error "no generic method 'OrderBy' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments."

how can i achieve this ?

regards

1 Answer 1

2

You are missing the fact that in contrast with Where, the OrderBy method has 2 generic type arguments (TSource and TKey). Hence you need to provide them both when generating a call:

var orderByCallExpression = Expression.Call(
    typeof(Queryable),
    method,
    new Type[] { source.ElementType, orderByExpression.Body.Type }, // <--
    whereCallExpression,
    Expression.Quote(orderByExpression));
Sign up to request clarification or add additional context in comments.

4 Comments

thx this solve my problem, btw is there anyway to change the filter expressions from "==" into "like" or "contains "
Sure, instead of Expression.Equal you could use Expression.Call(mbr, "Contains", Type.EmptyTypes, Expression.Constant("EVI0000101"))
once again thx @Ivan Stoev, is there any usefull documentation about this ? it can help me alot
Not that I know. All my experience is coming from self learning and experimenting. Explore the Expression class static methods. Or in most of the cases, it's easier to create sample compile time expression (e.g. Expression<Func<Foo, bool>> expr = x => x.Bar.Contains("Baz"); and examine the content inside the debugger. Then find the appropriate static methods to build it dynamically :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.