【问题标题】:Dynamic Lambda expressions for filter and sorting using children using c#使用 c# 使用子级进行过滤和排序的动态 Lambda 表达式
【发布时间】:2018-04-11 10:05:06
【问题描述】:

您好,我按照https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/how-to-use-expression-trees-to-build-dynamic-queries 中的指南在我的关系类中创建过滤器和排序,我需要使用子列“通道”进行过滤和排序

这是我的基类

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; }
}

这是仪表类

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

}

这是过滤和排序数据的代码:

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

实际上,“whereCallExpression”正在正常工作并过滤我想要的数据而没有错误,但排序逻辑给出错误“没有通用方法 'OrderBy' 类型 'System.Linq.Queryable' 与提供的类型兼容论据和论据。”

我怎样才能做到这一点?

问候

【问题讨论】:

    标签: c# lambda expression-trees linq-expressions ef-core-2.0


    【解决方案1】:

    您忽略了一个事实,即与 Where 相比,OrderBy 方法有 2 个泛型类型参数(TSourceTKey)。因此,您需要在生成呼叫时同时提供它们:

    var orderByCallExpression = Expression.Call(
        typeof(Queryable),
        method,
        new Type[] { source.ElementType, orderByExpression.Body.Type }, // <--
        whereCallExpression,
        Expression.Quote(orderByExpression));
    

    【讨论】:

    • thx 这解决了我的问题,顺便说一句,无论如何可以将过滤器表达式从“==”更改为“喜欢”或“包含”
    • 当然,你可以用Expression.Equal代替Expression.Call(mbr, "Contains", Type.EmptyTypes, Expression.Constant("EVI0000101"))
    • 再次感谢@Ivan Stoev,是否有任何有用的文档?它可以帮助我很多
    • 我不知道。我所有的经验都来自自我学习和实验。探索Expression 类静态方法。或者在大多数情况下,创建示例编译时表达式更容易(例如Expression&lt;Func&lt;Foo, bool&gt;&gt; expr = x =&gt; x.Bar.Contains("Baz"); 并检查调试器内的内容。然后找到适当的静态方法来动态构建它:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多