一、数据存储层
1、查找分页列表
在写用户列表时遇到了问题,考虑到用户可能会较多的情况需要分页,在数据存储层写的方法是public IQueryable<T> FindPageList<TKey>(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, bool asc)。
主要问题就在红色的order这儿,这个参数不好传递,比如:如果是已ID来排序哪TKey类型是int,如果以注册时间来排序哪TKey类型就是datetime。如果我在业务逻辑层写一个函数可以支持选择排序类型,那么我没有办法声明一个变量既可以存储TKey为int的值,又可以存储datetime的值,那么排序就要写成下面这个样子,感觉不舒服。
//排序 switch(order) { case 0://ID升序 _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.UserID, true).ToList(); break; case 1://ID降序 _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.UserID, false).ToList(); break; case 2://注册时间降序 _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.RegTime, true).ToList(); break; case 3://注册时间升序 _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.RegTime, false).ToList(); break; case 4://最后登录时间升序 _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.LastLoginTime, true).ToList(); break; case 5://最后登录时间降序 _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.LastLoginTime, false).ToList(); break; default://ID降序 _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.UserID, false).ToList(); break; }
后来将TKey设为dynamic类型,不论Expression<Func<T, dynamic>> order = u => u.UserID 或者u => u.RegTime都可以编译通过,但是一运行就会出错。
前几天没写博客一直在考虑这个问题,后来还是换成用字符串的方式来动态排序。 步骤如下:
Ninesky.DataLibrary[右键]->添加->类,输入类名OrderParam
namespace Ninesky.DataLibrary { /// <summary> /// 排序参数 /// </summary> public class OrderParam { /// <summary> /// 属性名 /// </summary> public string PropertyName { get; set; } /// <summary> /// 排序方式 /// </summary> public OrderMethod Method { get; set; } } /// <summary> /// 排序方式 /// </summary> public enum OrderMethod { /// <summary> /// 正序 /// </summary> ASC, /// <summary> /// 倒序 /// </summary> DESC } }
打开Ninesky.DataLibrary/Repository.cs,将方法public IQueryable<T> FindPageList<TKey>(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, bool asc)的代码修改为
/// <summary> /// 查找分页列表 /// </summary> /// <param>每页记录数。必须大于1</param> /// <param>页码。首页从1开始,页码必须大于1</param> /// <param>总记录数</param> /// <param>查询表达式</param> /// <param>排序【null-不设置】</param> public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, OrderParam[] orderParams) { if (pageIndex < 1) pageIndex = 1; if (pageSize < 1) pageSize = 10; IQueryable<T> _list = DbContext.Set<T>().Where(where); var _orderParames = Expression.Parameter(typeof(T), "o"); if (orderParams != null && orderParams.Length > 0) { for (int i = 0; i < orderParams.Length; i++) { //根据属性名获取属性 var _property = typeof(T).GetProperty(orderParams[i].PropertyName); //创建一个访问属性的表达式 var _propertyAccess = Expression.MakeMemberAccess(_orderParames, _property); var _orderByExp = Expression.Lambda(_propertyAccess, _orderParames); string _orderName = orderParams[i].Method == OrderMethod.ASC ? "OrderBy" : "OrderByDescending"; MethodCallExpression resultExp = Expression.Call(typeof(Queryable), _orderName, new Type[] { typeof(T), _property.PropertyType }, _list.Expression, Expression.Quote(_orderByExp)); _list = _list.Provider.CreateQuery<T>(resultExp); } } totalNumber = _list.Count(); return _list.Skip((pageIndex - 1) * pageIndex).Take(pageSize); }
方法中排序参数(OrderParam[]) 使用数组,是考虑到多级排序的情况。对FindPageList重载代码进行修改,修改完的代码如下:
//查找实体分页列表 #region FindPageList /// <summary> /// 查找分页列表 /// </summary> /// <param>每页记录数。必须大于1</param> /// <param>页码。首页从1开始,页码必须大于1</param> /// <param>总记录数</param> /// <returns></returns> public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber) { OrderParam _orderParam = null; return FindPageList(pageSize, pageIndex, out totalNumber, _orderParam); } /// <summary> /// 查找分页列表 /// </summary> /// <param>每页记录数。必须大于1</param> /// <param>页码。首页从1开始,页码必须大于1</param> /// <param>总记录数</param> /// <param>排序键</param> /// <param>是否正序</param> /// <returns></returns> public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, OrderParam orderParam) { return FindPageList(pageSize, pageIndex, out totalNumber, (T)=> true, orderParam); } /// <summary> /// 查找分页列表 /// </summary> /// <param>每页记录数。必须大于1</param> /// <param>页码。首页从1开始,页码必须大于1</param> /// <param>总记录数</param> /// <param>查询表达式</param> public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where) { OrderParam _param = null; return FindPageList(pageSize, pageIndex, out totalNumber, where, _param); } /// <summary> /// 查找分页列表 /// </summary> /// <param>每页记录数。</param> /// <param>页码。首页从1开始</param> /// <param>总记录数</param> /// <param>查询表达式</param> /// <param>排序【null-不设置】</param> /// <returns></returns> public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, OrderParam orderParam) { OrderParam[] _orderParams = null; if (orderParam != null) _orderParams = new OrderParam[] { orderParam }; return FindPageList(pageSize, pageIndex, out totalNumber, where, _orderParams); } /// <summary> /// 查找分页列表 /// </summary> /// <param>每页记录数。</param> /// <param>页码。首页从1开始</param> /// <param>总记录数</param> /// <param>查询表达式</param> /// <param>排序【null-不设置】</param> public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, OrderParam[] orderParams) { if (pageIndex < 1) pageIndex = 1; if (pageSize < 1) pageSize = 10; IQueryable<T> _list = DbContext.Set<T>().Where(where); var _orderParames = Expression.Parameter(typeof(T), "o"); if (orderParams != null && orderParams.Length > 0) { for (int i = 0; i < orderParams.Length; i++) { //根据属性名获取属性 var _property = typeof(T).GetProperty(orderParams[i].PropertyName); //创建一个访问属性的表达式 var _propertyAccess = Expression.MakeMemberAccess(_orderParames, _property); var _orderByExp = Expression.Lambda(_propertyAccess, _orderParames); string _orderName = orderParams[i].Method == OrderMethod.ASC ? "OrderBy" : "OrderByDescending"; MethodCallExpression resultExp = Expression.Call(typeof(Queryable), _orderName, new Type[] { typeof(T), _property.PropertyType }, _list.Expression, Expression.Quote(_orderByExp)); _list = _list.Provider.CreateQuery<T>(resultExp); } } totalNumber = _list.Count(); return _list.Skip((pageIndex - 1) * pageIndex).Take(pageSize); } #endregion
2、查找列表
基于分页列表同样的原因,对FindList方法也进行修改。