突发奇想-关于列表页面查询条件自动组装的实现

此方法不仅使用于ASP.NET WEB FORM ,而且适用于ASP.NET MVC。

当列表页面需要大量的查询条件,你该怎么办?

你是否厌倦了一个个查询条件的拼接?

你是否在想能不能有一种工具让这些查询条件自动组装?

今天,联想到ASP.NET MVC的模型绑定以及前台验证的实现思想,突发奇想,想要开发一个能够自动组装查询条件并且自动拼接成sql查询条件的工具。

原始方法的实现                     

第一步:列表页面查询表单的建立

由于本人几乎不会拖拽服务端框架,以前在解决列表页面多条件搜索的的实现方法是,通过js将查询条件极其值通过js拼接成一个url后缀的ur,然后通过get方式提交到后台,然后再才拆卸url后缀,最后手动拼接sql语句,其过程真是十分繁琐无味。

以前的做法前台代码如下所示:

l

 <script type="text/javascript">
        $(function () {
            $("#search").click(function(){
//url的拼接
                window.location.href="<%=ListUrl%>?ddlsuggestionType="+$("#ddlsuggestionType").val()+"&key="+$("#txtkey").val()+"&txtFrom="+$("#txtFrom").val()+"&txtTo="+$("#txtTo").val();
            });
        })
      
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <div class="alert alert-info">当前位置<b class='tip'></b><%=ListTitle %></div>
      
        <table class="tb">
           
            <tr height="45">
                <th>意见分类:<select id="ddlsuggestionType" class="ipt width200 " runat="server"></select>
                    关键字:<input type="text" id="txtkey" runat="server" class="ipt width200 " />
                    发布人登录名:<input type="text" id="txtFrom" runat="server" class="ipt width200 " />
                    接收人登录名:<input type="text" id="txtTo" runat="server" class="ipt width200 " />
                    <input type="button" id="search" class="btn" value="搜索" />
                </th>
            </tr>
            
            <tr height="45">
                <th>
                    <input type="button" class="btn  btn-primary" onclick='window.location.href="<%=EditUrl %>    ";' value="添加" />
                    &nbsp;&nbsp;
                     <input type="button" class="btn" onclick='window.location.href=window.location.href;' value="刷新" />
                </th>
            </tr>
        </table>
        <table class="tb" id="list">

第二步:url参数的拆卸以及sql条件的拼接

后台代码如下:

 1 //拆卸url参数
 2  private void BindData()
 3     {
 4         GetSuggestionTypeList();
 5         var suggestionType = Request.QueryString["ddlsuggestionType"];
 6         var key = Request.QueryString["key"];
 7         var txtFrom = Request.QueryString["txtFrom"];
 8         var txtTo = Request.QueryString["txtTo"];
 9         var userType = GetUser().UserType;
10         var entitys = BLL.BLLSession.Info_SuggestionBLL.GetSearchRptEntitys(suggestionType, key, userType,GetUser().Id,txtFrom,txtTo, Pager.CurrentPageIndex, Pager.PageSize, out  RowCount, out  PageCount);
11         BindRptData(rptList, entitys);
12         Pager.RecordCount = RowCount;
13         ddlsuggestionType.Value = suggestionType;
14         txtkey.Value = key;
15     }
16 
17 //sql的拼接
18  public List<Info_Suggestion> GetSearchRptEntitys(string suggestionType,string key,int userType,int userid,string txtFrom,string txtTo,int PageIndex, int PageSize, out int RowCount, out int PageCount)
19         {
20             string where = " and Deleted=0";
21             if (!string.IsNullOrEmpty(suggestionType) && suggestionType != "-1")
22             {
23                 where += " and SuggestionTypeId=" + suggestionType;
24             }
25             if (!string.IsNullOrEmpty(key))
26             {
27                 where += " and KeyWord like '%" + key.Replace("'", "") + "%'";
28             }           
29             if (userType != 1)//管理员可以查看所有的
30             {
31                 where += " and (FromUser=" + userid + " or ToUser=" + userid + ")";
32             }
33             if (!string.IsNullOrEmpty(txtFrom))
34             {
35                 where += " and FromUsrName='" + txtFrom.Replace("'", "") + "'";
36             }
37             if (!string.IsNullOrEmpty(txtTo))
38             {
39                 where += " and ToUserName='" + txtTo.Replace("'", "") + "'";
40             }      
41             List<Model.Info_Suggestion> entitys = null;
42             entitys = GetPagedEntitys(PageIndex, PageSize, out RowCount, out PageCount, null, where, "Id desc");
43             return entitys;
44         }

现在我想做的是让前台url自动组装,后台自动拆卸url参数,并且自动拼接sql语句

列表页面查询条件自动组装的实现

的的

第一步:将查询条件放在请求方式为get 的form中

代码如下:

 1  <form method="get">
 2         <table class="tb">
 3             <tr  class="treven height45">
 4                 <th class="thCss">
 5                    标题: <input name="Title_string_like" type="text" id="Title_string_like" runat="server" class="ipt width200 " />
 6                      来源: <input name="FromWhere_string_like" type="text" id="FromWhere_string_like" runat="server" class="ipt width200 " />
 7                     <input type="submit" class="btn" value="搜索" />
 8                 </th>
 9             </tr>
10             <tr class="height45">
11                 <th>
12                     <input type="button" class="btn  btn-primary" onclick='window.location.href="<%=EditUrl %>    ";' value="添加" />
13                     &nbsp;&nbsp;
14                      <input type="button" class="btn" onclick='window.location.href=window.location.href;' value="刷新" />
15                 </th>
16             </tr>
17         </table>
18     </form>

说明:上述代码会自动拼接url参数,也许你发现了表单的name很特别,这里使用的是约定大于配置的思想(如果你了解过mvc的话会发现其中到处都充斥着这种思想,比如mvc前台验证机制等等)。查询表单的那么格式为name_[int|string]_[like|equal],name代表对应的数据库字段名称,int和string代表的是数据类型,datetime类型默认为int类型,like代表模糊查询(暂不支持左模糊和右模糊),equal代表等值查询。我们约定以此方式为查询表单命名,方便在后台对此表单自动拆卸,组装sql条件。

第二步:建造url参数自动拆卸组装sql条件的工具

方法如下:

 1  public string GetQueryString(string name)
 2         {
 3            string temp= Request.QueryString[name];
 4            return string.IsNullOrEmpty(temp) ? "" : temp;
 5         }
 6         /// <summary>
 7         /// 自动组合拼接查询语句-使用约定大于配置的思想
 8         /// 查询表单的那么格式为name_[int|string]_[like|equal],name代表对应的数据库字段名称,int和string代表的是数据类型,datetime类型默认为int类型,like代表模糊查询(暂不支持左模糊和右模糊),equal代表等值查询。
 9         /// </summary>
10         /// <returns></returns>
11         public string GetQueryString()
12         {
13             string where = "";
14             System.Collections.Specialized.NameValueCollection collection = Request.QueryString;
15             var keys= collection.AllKeys;//key 的格式为 name_[int|string]_[like|equal]
16             foreach (var key in keys)
17             {
18                 string[] split = key.ToString().Split('_');
19                 string name = split[0];                
20                 string type = split[1] == "int" ? "" : "'";               
21                 string le = split[2] == "equal" ? "=" : "like";
22                 string l = le == "like" ? "%" : "";
23                 string value = GetQueryString(key.ToString());
24                 if (type=="'")
25                 {
26                     value = value.Replace("'","");//手动过滤掉',不足之处  应该使用参数化查询
27                 }
28                 if (!string.IsNullOrEmpty(value))
29                 {
30                     string tempStr = string.Format(" and {0} {1} {2}{3}{4}{3}{2} ", name, le, type, l, value);
31                     where += tempStr;
32 
33                 }                
34             }
35             return where;
36             
37         }

说明:我们知道sql的查询条件有等值查询和模糊查询(这里暂不考虑左模糊和右模糊),sql里面的值类型大致可以分为整型和字符串类型,我们把bit类型和datetime类型看做是整型,因为它们在值的两端不会加 "'"。这样我们可以根据我们前面在查询列表页面以name_[int|string]_[like|equal]的方式命名表单。具体操作,在以上代码中可以看到,不作说明,关于数据非法性验证在这里没做说明。

数据查询方法如下

 private void BindData()
    {
        string where=GetQueryString();
        var entitys = bll.GetPagedEntitys(Pager.CurrentPageIndex, Pager.PageSize, out RowCount, out PageCount,  where, null);

        BindRptData(rptList, entitys);
        Pager.RecordCount = RowCount;
    }

有些朋友该说,现在我们都使用的是强类型ORM框架处理数据的CURD。你怎么还在这里拼接sql语句,其实在这里我的底层操作数据库的也是强类型ORM框架EF。但是我个人认为针对于多条件查询的方法,使用Lamda作为条件显的特别臃肿。而我恰恰是利用了EF支持原生态的sql查询而且可以生成强类型model的特性拼接sql。这样还有一个好处是性能会有所提高。

但是经过使用sql server profiler跟踪发现了两个不足之处。

1.EF自动生成的sql分页语句并不是性能最好的分页语句(其实微软这样做是有原因的)。

2.如果直接使用EF提供的拼接sql语句结合分页查询时,跟踪发现对数据的分页是在内存中进行的(这实在太可怕了!!!)。

以上言论纯属本人言论,如有不妥或者错误的地方欢迎指正,同时在下篇博客我将给出以上两个问题的解决方案。

原文地址:https://www.cnblogs.com/eggTwo/p/3682955.html