如何指定谓词的类型,直到运行时我才知道?

我的存储库方法从数据库中提取东西。 它接受排序顺序作为参数:

IEnumerable getCars(Expression<Func> sort); 

我使用TSortKey ,因为我不知道在运行时将使用哪个属性,它可能是x => x.Namex => x.Make是字符串,但也可能是x => x.History.Age是一个整数。

用户选择排序顺序,然后在交换机中设置排序谓词并调用该方法。

  Expression<Func> 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,然后抛出。

那么我该如何解决这个问题呢?

问题是Expression>为值类型属性生成额外的Convert ,EF不喜欢并抛出NotSupportedException

您可以在存储库类中使用以下帮助程序方法而不是OrderBy 。 它的作用是在需要时剥离Convert表达式并动态调用Queryable.OrderBy方法:

 public static partial class EFExtensions { public static IOrderedQueryable SortBy(this IQueryable source, Expression> 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)source.Provider.CreateQuery(orderByCall); } }