zoukankan      html  css  js  c++  java
  • 【分享】(性能优化)思考数据列表中“特殊的列”

      数据列表在应用程序中十分常见和普遍,尤其是管理类的软件操作界面,如:一个待办列表,邮件列表,用户列表等。数据列表的数据源是由我们通过数据查询,逻辑运算,最终展示为列表。

      我们来看一种需求场景,假设列表中有一个“特殊的列“,它的数据不直接对应为数据库的列,或者是视图中的列,而是需要通过查询另外的关联表,通过计算得出,那么在绑定数据的时候,如何绑定上去呢?

    假如:有一张表单表(tab_FormData),列如下:

          Id,FormId(表单Id),Title(标题),Content(内容)。。。

    和一张任务表(tab_TaskInfo),列如下:

          Id,FormId(外键与tab_FormData的FormId),UserId(任务所有者Id),UserName(用户姓名),Comment(批示),Status(办理状态),CreateTime(任务创建时间)。。。

      当流程走到一个节点B时,一个表单可能对应着多个该节点的任务。如:该节点为【领导审批】节点,有三个领导做了批示(对应着任务表中三条记录),批示的内容分别为(圈阅,请张三领导阅,圈阅),当流转到下一节点【分发】时,需要补充张三领导,然后再回到【领导审批】节点,让张三领导去审批。那么在待办【分发】列表中,需要提示某一条公文是否有领导批示的不是圈阅的意见。如果存在,就在列表上标记出来,不存在就不标记。要显示的列表如下:有4列

      FormId,Title,Content,提醒()

       001      公文的标题   公文的内容  是

    最后一列,是通过表单Id从任务表中查询得出。伪linq代码:

    public static bool IsExist(string formId)

    {

      var query=from t in ObjectContext.tab_TaskInfo

            where t.FormId=formId && t.NodeId=领导节点 && t.Comment!="圈阅"

            select t;

      return query.Count()>0;

    }

    在循环绑定列表的时候,每一行数据都需要去做上面的查询,以便绑定最后一列。

    提问:有没有更好的解决方法,去绑定像上面这种情况的“特殊列”呢?

    如果把”特殊列“的逻辑封装成一个方法,是比较直观的做法。在上述情况下,则带来的是多次查询数据库,性能有所损失。

    解决方法:

      1.如果只查询一次数据库,就能得到所有的列,这样最好了。做表连接查询

      2.将特殊列的逻辑放在一个函数中,这样便于复杂逻辑处理,直观。这样这个”特殊列“就需要多次查询数据库。有些情况下,可能需要连接多张表才能得到结果。

    给出另外一种思路:列表中除”特殊列“之外的进行(第一次查询),在把(第一次查询)相关的数据进行第二次查询,然后在内存中把这两次的查询结果处理拼接起来。

    当然这个列表是需要分页显示的。给出linq伪代码:           

    //获取和当前页相关的数据列表(第二次查询),第一个参数当前页的列表,返回当前页相关的任务列表
    Func<IEnumerable<tab_FormData>, IEnumerable<tab_TaskInfo>> getGridContext = rows =>
    {
    return FormDataBLL.GetLeaderTasks(rows.Select(p => p.Formid).ToArray());//这里查询出符合条件的结果(t.NodeId=领导节点 && t.Comment!="圈阅")
    };
    //列筛选表达式
    Func<tab_FormData, IEnumerable<tab_TaskInfo>, object> selector = (row, gridContext) =>//row表示当前行,gridContext表示当前页的相关数据列表
    {
    var hasLeaderComment = gridContext.Where(p => p.formid == row.formid)
    .Count() > 0;//内存处理
    return new
    {
    id = row.id,
    formid = row.formid,
    Title = row.Title,
    Content = row.Content,
    HasComment = hasLeaderComment
                    };
    };


    页面绑定伪代码:

    JQueryUI.GridRender<tab_FormData, tab_TaskInfo>(source, getGridContext, selector, context.Request, context.Response);

    实现的关键代码:

    var  viewPageList = pageData.ToList();//一页的数据,(第一次查询)
    //重写行
    if (viewPageList.Count > 0)
    {
    tempList = new List<object>();
    foreach (var item in viewPageList)
    {
    var model = selector(item, viewPageList);
    tempList.Add(model);
    }
    }

    string jsonData = DataConvertUtility.ToJson(tempList);//得到最终的所有列,用于显示

    总结:这样带有“特殊列”的列表,只需要查询两次数据库,就可以得到需要的结果,当然这是取一个平衡点,上述的当前页的相关的任务列表数据量不大。

    好了,时间有点晚了,睡觉,下次再补充下,请各位同学谅解,如有疑问,提出来我们一起讨论,共同进步,谢谢!

  • 相关阅读:
    centos 安装 TortoiseSVN svn 客户端
    linux 定时任务 日志记录
    centos6.5 安装PHP7.0支持nginx
    linux root 用户 定时任务添加
    composer 一些使用说明
    laravel cookie写入
    laravel composer 安装指定版本以及基本的配置
    mysql 删除重复记录语句
    linux php redis 扩展安装
    linux php 安装 memcache 扩展
  • 原文地址:https://www.cnblogs.com/skysoft001/p/2313859.html
Copyright © 2011-2022 走看看