zoukankan      html  css  js  c++  java
  • AppBox升级进行时

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理、职称管理、部门管理、角色管理、角色权限管理等模块。

     

    Entity Framework提供的排序功能

     再来回顾一下上篇文章,加载用户列表并进行排序数据库分页的代码

    var q = DB.Users.Include(u => u.Dept);
     
    // 在用户名称中搜索
    string searchText = ttbSearchMessage.Text.Trim();
    if (!String.IsNullOrEmpty(searchText))
    {
        q = q.Where(u => u.Name.Contains(searchText) || u.ChineseName.Contains(searchText) || u.EnglishName.Contains(searchText));
    }
     
    // 过滤启用状态
    if (rblEnableStatus.SelectedValue != "all")
    {
        q = q.Where(u => u.Enabled == (rblEnableStatus.SelectedValue == "enabled" ? true : false));
    }
     
    // 在查询添加之后,排序和分页之前获取总记录数
    Grid1.RecordCount = q.Count();
     
    // 排列
    q = q.OrderBy(u => u.Name);
     
    // 数据库分页
    q = q.Skip(Grid1.PageIndex * Grid1.PageSize).Take(Grid1.PageSize);
     
    Grid1.DataSource = q;
    Grid1.DataBind();
    

    让我们把关注点集中到排序代码上:

    q = q.OrderBy(u => u.Name);
    

    在FineUI实际应用中,我们一般是从表格的 SortField 中读取排序字段,显然EF提供的OrderBy无法接受字符串表示的排序字段。

    手工创建Lamba表达式  

    通过搜索发现了这个帖子:http://stackoverflow.com/questions/10072250/generic-funct-k-to-sort-collections-of-different-types/10074873

    据此我们可以写出如下的代码:

    public Expression<Func<T, To>> GetSortExpression<T, To>(String sortBy)
    {
        var param = Expression.Parameter(typeof(T), "x");
        Expression expr = Expression.Property(param, sortBy);
        return Expression.Lambda<Func<T, To>>(expr, param);
    }
     
     
    protected IQueryable<T> Sort<T>(IQueryable<T> q, FineUI.Grid grid)
    {
        string sortField = grid.SortField;
     
        if (grid.SortDirection == "ASC")
        {
            q = q.OrderBy(GetSortExpression<T, object>(sortField));
        }
        else
        {
            q = q.OrderByDescending(GetSortExpression<T, object>(sortField));
        }
     
        return q;
    }
    

    经过测试,我们发现这个方法不支持bool, int, DateTime, DateTime?类型的列排序。

    经过扩展后的代码如下所示:

    protected IQueryable<T> Sort<T>(IQueryable<T> q, FineUI.Grid grid)
    {
        string sortField = grid.SortField;
        var propertyType = typeof(T).GetProperty(sortField).PropertyType;
     
        if (grid.SortDirection == "ASC")
        {
            if (propertyType == typeof(bool))
            {
                q = q.OrderBy(GetSortExpression<T, bool>(sortField));
            }
            else if (propertyType == typeof(int))
            {
                q = q.OrderBy(GetSortExpression<T, int>(sortField));
            }
            else if (propertyType == typeof(DateTime))
            {
                q = q.OrderBy(GetSortExpression<T, DateTime>(sortField));
            }
            else if (propertyType == typeof(DateTime?))
            {
                q = q.OrderBy(GetSortExpression<T, DateTime?>(sortField));
            }
            else
            {
                q = q.OrderBy(GetSortExpression<T, object>(sortField));
            }
        }
        else
        {
            if (propertyType == typeof(bool))
            {
                q = q.OrderByDescending(GetSortExpression<T, bool>(sortField));
            }
            else if (propertyType == typeof(int))
            {
                q = q.OrderByDescending(GetSortExpression<T, int>(sortField));
            }
            else if (propertyType == typeof(DateTime))
            {
                q = q.OrderByDescending(GetSortExpression<T, DateTime>(sortField));
            }
            else if (propertyType == typeof(DateTime?))
            {
                q = q.OrderByDescending(GetSortExpression<T, DateTime?>(sortField));
            }
            else
            {
                q = q.OrderByDescending(GetSortExpression<T, object>(sortField));
            }
        }
     
        return q;
    }
    

    但这种做法过于臃肿,有没有更好的办法呢?

    更好的SortBy扩展方法  

    后来,我们发现了这篇文章:http://stackoverflow.com/questions/3945645/sorting-gridview-with-entity-framework

    通过对 IQueryable<T> 进行扩展,提供了接受类似 "Name DESC", "CreateTime", "CreateTime DESC" 参数的 SortBy 方法,更具有通用性。

    原始的SortBy扩展方法:

    public static class QueryExtensions {
        public static IQueryable<T> SortBy<T>(this IQueryable<T> source, string propertyName) {
            if (source == null) {
                throw new ArgumentNullException("source");
            }
            // DataSource control passes the sort parameter with a direction
            // if the direction is descending          
            int descIndex = propertyName.IndexOf(" DESC");
            if (descIndex >= 0) {
                propertyName = propertyName.Substring(0, descIndex).Trim();
            }
     
            if (String.IsNullOrEmpty(propertyName)) {
                return source;
            }
     
            ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
            MemberExpression property = Expression.Property(parameter, propertyName);
            LambdaExpression lambda = Expression.Lambda(property, parameter);
     
            string methodName = (descIndex < 0) ? "OrderBy" : "OrderByDescending";
     
            Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
                                                new Type[] { source.ElementType, property.Type },
                                                source.Expression, Expression.Quote(lambda));
     
            return source.Provider.CreateQuery<T>(methodCallExpression);
        }
    }
    

    不过这个方法不支持"Name ASC"形式的参数,所以我们进行了简单的修正,修正后的SortBy扩展方法:

    public static class QueryExtensions
    {
        public static IQueryable<T> SortBy<T>(this IQueryable<T> source, string sortExpression)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
     
            string sortDirection = String.Empty;
            string propertyName = String.Empty;
     
            sortExpression = sortExpression.Trim();
            int spaceIndex = sortExpression.Trim().IndexOf(" ");
            if (spaceIndex < 0)
            {
                propertyName = sortExpression;
                sortDirection = "ASC";
            }
            else
            {
                propertyName = sortExpression.Substring(0, spaceIndex);
                sortDirection = sortExpression.Substring(spaceIndex + 1).Trim();
            }
     
            if (String.IsNullOrEmpty(propertyName))
            {
                return source;
            }
     
            ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
            MemberExpression property = Expression.Property(parameter, propertyName);
            LambdaExpression lambda = Expression.Lambda(property, parameter);
     
            string methodName = (sortDirection == "ASC") ? "OrderBy" : "OrderByDescending";
     
            Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
                                                new Type[] { source.ElementType, property.Type },
                                                source.Expression, Expression.Quote(lambda));
     
            return source.Provider.CreateQuery<T>(methodCallExpression);
        }
     
    }
    

      

    优化后的排序分页代码

    首先在页面基类PageBase中定义排序和分页的代码(使用了前面定义的 SortBy 扩展函数):

    protected IQueryable<T> Sort<T>(IQueryable<T> q, FineUI.Grid grid)
    {
        return q.SortBy(grid.SortField + " " + grid.SortDirection);
    }
     
    protected IQueryable<T> SortAndPage<T>(IQueryable<T> q, FineUI.Grid grid)
    {
        return Sort(q, grid).Skip(grid.PageIndex * grid.PageSize).Take(grid.PageSize);
    }
    

      

    最终查询用户列表的代码:

    var q = DB.Users.Include(u => u.Dept);
     
    // 在用户名称中搜索
    string searchText = ttbSearchMessage.Text.Trim();
    if (!String.IsNullOrEmpty(searchText))
    {
        q = q.Where(u => u.Name.Contains(searchText) || u.ChineseName.Contains(searchText) || u.EnglishName.Contains(searchText));
    }
     
    // 过滤启用状态
    if (rblEnableStatus.SelectedValue != "all")
    {
        q = q.Where(u => u.Enabled == (rblEnableStatus.SelectedValue == "enabled" ? true : false));
    }
     
    // 在查询添加之后,排序和分页之前获取总记录数
    Grid1.RecordCount = q.Count();
     
    // 排列和数据库分页
    q = SortAndPage<User>(q, Grid1);
     
     
    Grid1.DataSource = q;
    Grid1.DataBind();
    

      

    下载或捐赠AppBox

    1. AppBox v2.1 是免费软件,免费提供下载:http://fineui.com/bbs/forum.php?mod=viewthread&tid=3788 

    2. AppBox v3.0 是捐赠软件,你可以通过捐赠作者来获取AppBox v3.0的全部源代码(http://fineui.com/donate/)。

  • 相关阅读:
    php基本语法之逻辑运算符
    HTML5实现端访问时禁止放大和缩小网页
    javascript simple MVC
    GIS开发离线地图应用-初识gis
    百度应用开发--日期大写转换
    ThinkPHP与EasyUI整合之三(searchbox):在datagrid中查询指定记录
    ThinkPHP与EasyUI整合之二(datagrid):删除多条记录
    面向对象----类和对象
    Java 基本语法----数组
    Java 基本语法----流程控制
  • 原文地址:https://www.cnblogs.com/sanshi/p/3277507.html
Copyright © 2011-2022 走看看