我的存储库方法从数据库中提取东西。它接受排序顺序作为参数:
IEnumerable<Car> getCars<TSortKey>(Expression<Func<Car, TSortKey>> sort);
我使用TSortKey
,因为我不知道在运行时将使用哪个属性,它可能是x => x.Name
或x => x.Make
这是字符串,但它也可能是x => x.History.Age
这是一个整数。
用户选择排序顺序,然后在交换机中设置排序谓词并调用该方法。
Expression<Func<Car, object>> sortPredicate;
switch (sortOption) {
case SortOption.Name: sortPredicate = s => s.Name; break;
case SortOption.Make: sortPredicate = s => s.Make; break;
case SortOption.Age: sortPredicate = s => s.History.Age; break;
default: sortPredicate = s => s.Name; break;
}
var cars = repo.getCars(sortPredicate);
我在谓词中使用object
,因为直到运行时我才知道类型。但是这会生成错误的SQL,然后抛出。
那么我该如何解决这个问题呢?
答案 0 :(得分:2)
问题在于Expression<Func<T, object>>
为值类型属性生成了额外的Convert
,EF不喜欢并抛出NotSupportedException
。
您可以在存储库类中使用以下帮助程序方法代替OrderBy
。它的作用是在需要时剥离Convert
表达式并动态调用Queryable.OrderBy
方法:
public static partial class EFExtensions
{
public static IOrderedQueryable<T> SortBy<T>(this IQueryable<T> source, Expression<Func<T, object>> keySelector)
{
var body = keySelector.Body;
if (body.NodeType == ExpressionType.Convert)
body = ((UnaryExpression)keySelector.Body).Operand;
var selector = Expression.Lambda(body, keySelector.Parameters);
var orderByCall = Expression.Call(
typeof(Queryable), "OrderBy", new[] { typeof(T), body.Type },
source.Expression, Expression.Quote(selector));
return (IOrderedQueryable<T>)source.Provider.CreateQuery(orderByCall);
}
}