Linq EF Core 3.1运行时生成的表达式全部失败,无法在服务器上处理查询

Linq EF Core 3.1运行时生成的表达式全部失败,无法在服务器上处理查询,linq,entity-framework-core,expression-trees,Linq,Entity Framework Core,Expression Trees,在过去,我们可以使用如下代码: public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName) { // LAMBDA: x => x.[PropertyName] var parameter = Expression.Parameter(typeof(TSource), "x")

在过去,我们可以使用如下代码:

public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)
{
    // LAMBDA: x => x.[PropertyName]
    var parameter = Expression.Parameter(typeof(TSource), "x");
    Expression property = Expression.Property(parameter, propertyName);
    var lambda = Expression.Lambda(property, parameter);

    // REFLECTION: source.OrderBy(x => x.Property)
    var orderByMethod = typeof(Queryable).GetMethods().First(x => x.Name == "OrderBy" && x.GetParameters().Length == 2);
    var orderByGeneric = orderByMethod.MakeGenericMethod(typeof(TSource), property.Type);
    var result = orderByGeneric.Invoke(null, new object[] { source, lambda });

    return (IOrderedQueryable<TSource>)result;
}
public静态IOrderedQueryable OrderBy(此IQueryable源,字符串propertyName)
{
//LAMBDA:x=>x.[PropertyName]
var参数=表达式参数(typeof(TSource),“x”);
Expression property=Expression.property(参数,propertyName);
var lambda=Expression.lambda(属性、参数);
//反射:source.OrderBy(x=>x.Property)
var orderByMethod=typeof(Queryable).GetMethods().First(x=>x.Name==“OrderBy”&&x.GetParameters().Length==2);
var orderByGeneric=orderByMethod.MakeGenericMethod(typeof(TSource),property.Type);
var result=orderByGeneric.Invoke(null,新对象[]{source,lambda});
返回(IOrderedQueryable)结果;
}
通过执行订单,但在EF Core 3.1中现在失败

而在source.QueryBy(x=>EF.Property(x,“Name”))中的使用给出了EF.Property错误的正确用法,因此我不知道如何避免这些错误,并且仍然在IQueryable上构建动态表达式


我做错了什么?

你没有做错什么-EF Core“为你”做错了:-(

不确定“过去”是什么意思,但EF Core从一开始就对一些他们称之为“非编译器生成”的表达式存在问题,如下面的文章

还有很多GitHub问题,比如

看起来它终于被修复了,但不幸的是没有包含在3.1中,所以我们不得不等到年底的5.0(1行更改!)

在此之前,您必须使用上述解决方法,例如使用以下
Expression.Property
replacement(基本上是源代码):

e、 g

应该解决这个问题


不相关,但您也可以从两个方面改进您的方法

首先,您可以通过使用“Prop1.Prop2.Prop3”这样的点分隔字符串轻松添加对嵌套属性的支持

其次,您可以简单地发出
Expression.Call
Queryable.OrderBy
,而不是反射

整个方法可以是这样的:

public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)
{
    var parameter = Expression.Parameter(source.ElementType, "x");
    var property = propertyName.Split(".")
        .Aggregate((Expression)parameter, Property);
    var selector = Expression.Lambda(property, new[] { parameter });
    var expression = Expression.Call(typeof(Queryable), nameof(Queryable.OrderBy),
        new[] { source.ElementType, property.Type },
        new[] { source.Expression, Expression.Quote(selector) });
    return (IOrderedQueryable<TSource>)source.Provider.CreateQuery(expression);
}
public静态IOrderedQueryable OrderBy(此IQueryable源,字符串propertyName)
{
var参数=Expression.parameter(source.ElementType,“x”);
var property=propertyName.Split(“.”)
.Aggregate((表达式)参数、属性);
var selector=Expression.Lambda(属性,新[]{parameter});
var expression=expression.Call(typeof(Queryable)、nameof(Queryable.OrderBy),
新[]{source.ElementType,property.Type},
新[]{source.Expression,Expression.Quote(选择器)});
返回(IOrderedQueryable)source.Provider.CreateQuery(表达式);
}

如果您还发布查询执行期间发生的实际异常消息,将非常有用
var property = Property(propertyName);
var property = propertyName.Split(".")
    .Aggregate((Expression)parameter, Property);
public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)
{
    var parameter = Expression.Parameter(source.ElementType, "x");
    var property = propertyName.Split(".")
        .Aggregate((Expression)parameter, Property);
    var selector = Expression.Lambda(property, new[] { parameter });
    var expression = Expression.Call(typeof(Queryable), nameof(Queryable.OrderBy),
        new[] { source.ElementType, property.Type },
        new[] { source.Expression, Expression.Quote(selector) });
    return (IOrderedQueryable<TSource>)source.Provider.CreateQuery(expression);
}