使用 c# 使用子项进行过滤和排序的动态 Lambda 表达式
Dynamic Lambda expressions for filter and sorting using children using c#
你好,我按照 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/how-to-use-expression-trees-to-build-dynamic-queries 中的指南在我的关系 class 中创建过滤器和排序,我需要使用子列 "Channel"
进行过滤和排序
这是我的基地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; }
}
这是仪表 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; }
}
这是过滤和排序数据的代码:
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" 正在正常工作并无误地过滤我想要的数据,但排序逻辑出错 "no generic method 'OrderBy' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments."
我怎样才能做到这一点?
问候
您忽略了一个事实,即与 Where
相比,OrderBy
方法有 2 个通用类型参数(TSource
和 TKey
)。因此,您需要在生成呼叫时同时提供它们:
var orderByCallExpression = Expression.Call(
typeof(Queryable),
method,
new Type[] { source.ElementType, orderByExpression.Body.Type }, // <--
whereCallExpression,
Expression.Quote(orderByExpression));
你好,我按照 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/how-to-use-expression-trees-to-build-dynamic-queries 中的指南在我的关系 class 中创建过滤器和排序,我需要使用子列 "Channel"
进行过滤和排序这是我的基地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; }
}
这是仪表 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; }
}
这是过滤和排序数据的代码:
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" 正在正常工作并无误地过滤我想要的数据,但排序逻辑出错 "no generic method 'OrderBy' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments."
我怎样才能做到这一点?
问候
您忽略了一个事实,即与 Where
相比,OrderBy
方法有 2 个通用类型参数(TSource
和 TKey
)。因此,您需要在生成呼叫时同时提供它们:
var orderByCallExpression = Expression.Call(
typeof(Queryable),
method,
new Type[] { source.ElementType, orderByExpression.Body.Type }, // <--
whereCallExpression,
Expression.Quote(orderByExpression));