Вы не делаете ничего плохого - EF Core делает это неправильно "для вас": - (
Не уверен, что вы подразумеваете под "в прошлом", но у EF Core есть проблемы с некоторыми, что они называют «не сгенерированные компилятором» выражения с самого начала, такие как следующие сообщения SO
Как использовать унаследованные свойства в выражениях EF Core?
Почему Linq "где "выражение после выбора вычисляется локально при создании с помощью метода generi c?
Не удалось преобразовать выражение LINQ для базового свойства
и многих других GitHub выдает такие сообщения, как
Построение фильтра и / или OrderBy с помощью выражений для бросков промежуточного типа memberInfo в иерархии для сокращения MemberInitExpression # 19182 , но, к сожалению, не включен в 3.1, поэтому мы должны ждать 5.0 в конце года (для изменения 1 строки!).
До тех пор вы должны использовать упомянутые обходные пути, например, использовать следующую Expression.Property
замену (в основном код из Как использовать унаследованные свойства в выражениях EF Core? ):
static MemberExpression Property(Expression expression, string propertyName)
{
var propertyInfo = expression.Type.GetProperty(propertyName);
if (propertyInfo.ReflectedType != propertyInfo.DeclaringType)
propertyInfo = propertyInfo.DeclaringType.GetProperty(propertyName);
return Expression.MakeMemberAccess(expression, propertyInfo);
}
Например,
var property = Property(propertyName);
должен решить проблему.
Не имеет отношения, но вы также можете улучшить свой метод двумя способами.
Во-первых, вы можете легко добавить поддержку вложенных свойств через строку, разделенную точками, например «Prop1.Prop2.Prop3», используя
var property = propertyName.Split(".")
.Aggregate((Expression)parameter, Property);
Во-вторых, вместо отражения вы можете просто испустить 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);
}