c# – 如何将多个表达式传递给EFB的OrderBy?
我使用EF 4.2,但我预计这将适用于EF 4和4.1.
我想传递一个IQueryable< T>和多个表达式< Func< TSource,TKey>>一种方法,并且该方法将OrderBy和ThenBy应用于IQueryable< T>作为适当的. 我发现了this answer,并根据下面的方法写下: public IQueryable<User> ApplyOrderBy(IQueryable<User> query,IEnumerable<Expression<Func<User,IComparable>>> orderBy) { if (orderBy == null) { return query; } IOrderedQueryable<User> output = null; foreach(var expression in orderBy) { if (output == null) { output = query.OrderBy(expression); } else { output = output.ThenBy(expression); } } return output ?? query; } 只要我订单的属性是字符串,但是当我尝试通过int属性排序时,我会得到一个例外:
要解决这个问题的任何建议,还是一个不同的方法呢?我认为传递一个IEnumerable< Expression>但是然后将需要弄清楚如何转回到调用OrderBy的特定类型(例如,Expression< Func< User,int>). 解决方法
我无法解释为什么使用Int32不起作用但使用字符串.不是EDM都是“原始”类型,并不能同时实现IComparable?我不明白不同的行为.
无论如何,似乎有必要使用具体类型传递集合中的每个表达式,以避免出现失败的类型转换.换句话说,不是一个IComparable,而是一个int,一个字符串,一个DateTime等. 在这个答案中,我已经成功地实现了这一点:How to check for the presence of an OrderBy in a ObjectQuery<T> expression tree 定义一个不依赖于类型进行排序但不仅仅依赖实体类型的接口. (下面的例子被推广到任意实体,如果只需要用户删除通用参数,并用User替换可查询的TEntity.) public interface IOrderByExpression<TEntity> where TEntity : class { IOrderedQueryable<TEntity> ApplyOrderBy(IQueryable<TEntity> query); IOrderedQueryable<TEntity> ApplyThenBy(IOrderedQueryable<TEntity> query); } 定义该接口的实现,该接口现在将类型排序为第二个通用参数: public class OrderByExpression<TEntity,TOrderBy> : IOrderByExpression<TEntity> where TEntity : class { private Expression<Func<TEntity,TOrderBy>> _expression; private bool _descending; public OrderByExpression(Expression<Func<TEntity,TOrderBy>> expression,bool descending = false) { _expression = expression; _descending = descending; } public IOrderedQueryable<TEntity> ApplyOrderBy( IQueryable<TEntity> query) { if (_descending) return query.OrderByDescending(_expression); else return query.OrderBy(_expression); } public IOrderedQueryable<TEntity> ApplyThenBy( IOrderedQueryable<TEntity> query) { if (_descending) return query.ThenByDescending(_expression); else return query.ThenBy(_expression); } } 那么ApplyOrderBy将如下所示: public IQueryable<TEntity> ApplyOrderBy<TEntity>(IQueryable<TEntity> query,params IOrderByExpression<TEntity>[] orderByExpressions) where TEntity : class { if (orderByExpressions == null) return query; IOrderedQueryable<TEntity> output = null; foreach (var orderByExpression in orderByExpressions) { if (output == null) output = orderByExpression.ApplyOrderBy(query); else output = orderByExpression.ApplyThenBy(output); } return output ?? query; } 它可以用如下方式使用: var query = context.Users ... ; var queryWithOrderBy = ApplyOrderBy(query,new OrderByExpression<User,string>(u => u.UserName),// a string,asc new OrderByExpression<User,int>(u => u.UserId,true)); // an int,desc var result = queryWithOrderBy.ToList(); // didn't throw an exception for me 在OrderByExpression实例中明确指定泛型类型参数的需求不是很好,但是我找不到一种方法,以便编译器推断类型. (我希望这样做,因为编译器将User作为TEntity从ApplyOrderBy方法的查询中推断出来,所以我预计它知道OrderByExpression的TEntity(等于User),所以lambda参数u应该被称为用户然后编译器可以从UserName中导出类型为string,从UserId导出为int,但是这个理论显然是错误的,编译器抱怨并希望明确地显示泛型类型) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |