首页 > 代码库 > Entity Framework 多条件排序与分页的实现

Entity Framework 多条件排序与分页的实现

项目过程中遇到需要对数据源进行多条件排序的情况,

开始觉得很简单,分分钟搞定,当时的逻辑大概是将排序条件以及是否倒序写入Dictionary中,在方法中遍历此Dictionary进行排序(下面的方法附带了分页,其实觉得耦合度太高,感觉还是都分开比较好)

 

 

public IQueryable<T> GetListByPage<S>(int pageSize, int pageIndex, out int pageCount, Expression<Func<T, bool>> predicate, Dictionary<Expression<Func<T, S>>, bool> orderbyCondition = null){var temp = MyContext.Set<T>().Where(predicate);pageCount = temp.Count();if (orderbyCondition != null && orderbyCondition.Count > 0){int index = 1;foreach (var condition in orderbyCondition){if (index == 1){temp = condition.Value ? temp.OrderBy<T, S>(condition.Key) : temp.OrderByDescending<T, S>(condition.Key);index++;}else{temp = condition.Value ? (temp as IOrderedQueryable<T>).ThenBy(condition.Key) : (temp as IOrderedQueryable<T>).ThenByDescending(condition.Key);} }}temp = temp.Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);return temp.AsQueryable();}

 

满怀希望地打开了页面,看到了很骨感的现实-"出错了",分析了一下 原因是在传递Dictionary参数的时候,里面写入的泛型返回类型不同;

按照时间排序 返回类型就是Datetime ,按照序号排序 返回类型就是int 之后试着在传参的时候这么写

Dictionary<object,bool> conditionDic, 但实际执行的时候依然不行, EF必须指定返回类型.

为了不在每个entity的BLL都要改一遍, 我决定写一个底层的方法, 在网上查了一些资料,参考了其中一位大神的思路http://www.cnblogs.com/hun_dan/archive/2012/10/23/2735255.html

,完成了这个需求.

过程中的需要注意的地方大概有如下几点:

  1. 排序条件返回类型不一致
  2. 正序倒序不确定
  3. OrderBy和ThenBy(头次排序及后续排序)

 

大概思路:

定义一个接口,重写两个方法orderby和thenby, 用类型ExpressionCondition实现这个接口, 此外类型成员还有condition以及isDesc,并在构造函数中赋初值.

声明主调用函数,将排序条件作为数组ExpressionCondition[]传递;以下是实现代码

BaseEntity 为实体基类,其余实体只需要继承基类即可调用此方法

Interface:

 
   public interface IOrderByMultiCondition<T>        where T : BaseEntity    {        IOrderedQueryable<T> ApplyOrderBy(IQueryable<T> query);        IOrderedQueryable<T> ApplyThenBy(IOrderedQueryable<T> query);    }

 

Class

 public class OrderByMultiCondition<T, R> : IOrderByMultiCondition<T>        where T : BaseEntity    {        Expression<Func<T, R>> _expressionn;        bool _isDesc;        public OrderByMultiCondition(Expression<Func<T, R>> expression, bool IsDesc = false)        {            _expressionn = expression;            _isDesc = IsDesc;        }        public IOrderedQueryable<T> ApplyOrderBy(IQueryable<T> query)        {            if (_isDesc)            {                return query.OrderByDescending(_expressionn);            }            else                return query.OrderBy(_expressionn);        }        public IOrderedQueryable<T> ApplyThenBy(IOrderedQueryable<T> query)        {            if (_isDesc)            {                return query.ThenByDescending(_expressionn);            }            else                return query.ThenBy(_expressionn);        }    }

 

Repository

public IQueryable<T> GetListByPage(int pageSize, int pageIndex, out int pageCount, Expression<Func<T, bool>> predicate, params IOrderByMultiCondition<T>[] orderByExpressions)        {            var temp = MyContext.Set<T>().Where(predicate);            pageCount = temp.Count();            if (orderByExpressions != null)            {                IOrderedQueryable<T> afterFirstSort = null;                foreach (var expression in orderByExpressions)                {                    if (afterFirstSort == null)                    {                        afterFirstSort = expression.ApplyOrderBy(temp);                    }                    else                        afterFirstSort = expression.ApplyThenBy(afterFirstSort);                }                temp = afterFirstSort;            }            temp = temp.Skip<T>((pageIndex - 1) * pageSize)                .Take<T>(pageSize);            return temp.AsQueryable();        }