5

我希望能够firstby / thenby按如下方式应用组合排序:

allOrders().sort(s => s.ProductName, s => s.OrderDate)

所以以这篇文章为灵感,我写了这个扩展方法,编译得很好:

public static IQueryable<T> sort<T>(this IQueryable<T> entities, params 
  Expression<Func<T, object>>[] predicates) where T : class 
{
  var sorted = entities.OrderBy(predicates[0]);
  for (int i = 1; i < predicates.Length; i++)
    sorted = sorted.ThenBy(predicates[i]);

  return sorted;
}

而且我还尝试了这个简洁的版本,它也可以编译:

public static IQueryable<T> sort<T>(this IQueryable<T> entities, params 
  Expression<Func<T, object>>[] predicates) where T : class
{
  return predicates.Skip(1).Aggregate(
    entities.OrderBy(predicates[0]),
    (aggregate, currentPredicate) => aggregate.ThenBy(currentPredicate));
}

但是,如果我尝试按 a 排序,则会DateTime收到此异常:

无法将类型“System.DateTime”转换为类型“System.Object”。LINQ to Entities 仅支持转换 EDM 基元或枚举类型。

我究竟做错了什么?我正在使用 EF5。

4

2 回答 2

6

当您从返回 的 lambda 表达式返回值类型(例如intor )时,编译器会生成一个调用以将该值类型转换为装箱对象。 DateTimeobjectBox()

实体框架表达式解析器无法处理此框表达式。
唯一的解决方案是传递一个返回值类型的强类型 lambda 表达式。

为此,您可能会误用集合初始化器:

public class OrderingCollection<TEntity> : IEnumerable {
    public void Add<TProperty>(Expression<Func<TEntity, TProperty>>) {
        ...
    }
}

public static IQueryable<T> Sort<T>(this IQueryable<T> entities, 
                                    OrderingCollection<T> o) where T : class {
    ...
}


q = q.Sort(new OrderingCollection { s => s.ProductName, s => s.OrderDate });

集合初始值设定项允许您对任意数量的不同类型参数使用类型推断。

于 2012-10-24T20:27:09.790 回答
0

我认为您的问题在于Func<T, object>. 这意味着无论您对什么进行排序,您都将返回一个对象,而 EF 无法将其映射到数据库列类型。

OrderBy()函数同时接受 aTSource和 a TKey,因此您需要为每种排序提供键类型,这很快就会失控(请参阅 参考资料Tuple<T1,T2,T3,T4,T5,T6,T7,T8>)。

于 2012-10-24T20:29:39.650 回答