• 自动生成 Lambda查询和排序,从些查询列表so easy


    如下图查询页面,跟据不同条件动态生成lambda的Where条件和OrderBy,如果要增加或调整查询,只用改前台HTML即可,不用改后台代码

    前台代码:

     1     <div style="padding-bottom: 5px;" id="queryForm">
     2 
     3         <span>员工姓名:</span><input type="text" emptytext="ddd" data-options="{match:'in'}" class="mini-textbox" id="Age" />
     4         <span>部门:</span><input type="text" class="mini-textbox" data-options="{match:'like'}" id="Sex" />
     5 
     6         生日从  <input id="beg" format="yyyy-MM-dd" showokbutton="false" showclearbutton="true" data-options="{match:'from',innerkey:'Birthday'}" class="mini-datepicker" />
     7<input id="end" format="yyyy-MM-dd" showokbutton="false" showclearbutton="true" data-options="{match:'to',innerkey:'Birthday'}" class="mini-datepicker" />
     8 
     9         <span>年龄从:</span><input type="text" emptytext="ddd" data-options="{match:'from',innerkey:'Age'}" class="mini-textbox" id="bb" />
    10         <span>至:</span><input type="text" class="mini-textbox" data-options="{match:'to',innerkey:'Age'}" id="bd" />
    11 
    12         <a class="mini-button" iconcls="icon-search" onclick="search()">查找</a>
    13 
    14 
    15     </div>  
    16 
    17 
    18 <div id="datagrid1" ondrawcell="Link" onupdate="load" class="mini-datagrid" style=" 100%; height: 100%;" allowresize="true"
    19              idfield="Id" sortfield="Age" showpager="false" pagesize="-1" sizelist="[-1]" sortorder="asc" multiselect="true">
    20             <div property="columns">
    21                 <!--<div type="indexcolumn"></div>        -->
    22                 <div type="checkcolumn"></div>
    23                 <div field="UserName" data-options="{Func:'test'}" width="120" headeralign="center" allowsort="true">姓名</div>
    24                 <div field="Sex" renderer="SexShow" width="120" headeralign="center" allowsort="true">性别</div>
    25 
    26                 <div field="LoginName" width="120">登录名</div>
    27                 <div field="Password" width="120">密码</div>
    28                 <div field="Birthday" width="100">生日</div>
    29                 <div field="Age" width="100" allowsort="true">年龄</div>
    30                 <div field="Remark" align="right" width="100">备注</div>
    31 
    32 
    33                 <div field="Married" renderer="MarriedShow" width="100">婚否</div>
    34 
    35             </div>
    36         </div>
    View Code
    查询控件上的 data-options="{match:'from',innerkey:'Birthday'}" 后多个查询条件会组合成一个json数组,传到后台,反序列化成List<QueryItem>,
    排序条件Jquery 的Grid控件也会传到后台的,反序列化成SortItem,分页信息 反序列化成 Pager,详见后台代码。


    上后台代码:比较复杂
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 using App.Core;
      7 using System.Reflection;
      8 using System.Linq.Expressions;
      9 using System.Data.Entity;
     10 using System.Collections.Specialized;
     11 namespace App.PageBase.Query
     12 {
     13     //查询条件模型
     14     public class QueryItem 
     15     {
     16         public string match { get; set; }
     17         public string value { get; set; }
     18         public string key { get; set; }
     19         public string innerkey { get; set; }
     20 
     21     }
     22     //排序模型
     23     public class SortItem
     24     {
     25 
     26         public string sortField { get; set; }
     27         public string sortOrder { get; set; }
     28     }
     29     //列表分页模型
     30     public class Pager
     31     {
     32         public int pageSize
     33         {
     34             get;
     35             set;
     36         }
     37         public int pageIndex
     38         {
     39             get;
     40             set;
     41         }
     42         public int totalCount
     43         {
     44             get;
     45             set;
     46         }
     47 
     48     }
     49 
     50 
     51     //生成查询条件类
     52     public class QueryBulider<TEntity> where TEntity : class,new()
     53     {
     54         private Pager _pager;// = new Pager();
     55         private SortItem _sort;// = new SortItem();
     56         private List<QueryItem> _queryItems;//= new List<QueryItem>();
     57         public Pager pager
     58         {
     59             get { return _pager; }
     60             set { _pager = value; }
     61         }
     62         public SortItem sort
     63         {
     64             get { return _sort; }
     65             set { _sort = value; }
     66         }
     67         public List<QueryItem> queryItems
     68         {
     69             get { return _queryItems; }
     70             set { _queryItems = value; }
     71         }
     72         /// <summary>
     73         /// 根据 分页模型,排序模型,查询条件模型列表构造 自动查询生成器
     74         /// </summary>
     75         /// <param name="pager"></param>
     76         /// <param name="sort"></param>
     77         /// <param name="queryItems"></param>
     78         public QueryBulider(Pager pager, SortItem sort, List<QueryItem> queryItems)
     79         {
     80             this.pager = pager;
     81             this.sort = sort;
     82             this.queryItems = queryItems;
     83 
     84 
     85         }
     86         public QueryBulider()
     87         { }
     88     
     89         /// <summary>
     90         /// 根据HTTP实例化
     91         /// </summary>
     92         /// <param name="requstForm"></param>
     93         public QueryBulider(NameValueCollection requstForm)
     94         {
     95             string filter = requstForm["filter"];
     96             string pageIndex = requstForm["pageIndex"];
     97             string pageSize = requstForm["pageSize"];
     98             string sortField = requstForm["sortField"];
     99             string sortOrder = requstForm["sortOrder"];
    100 
    101             if (!string.IsNullOrEmpty(pageSize) && !string.IsNullOrEmpty(pageIndex)&&pageSize!="-1")
    102             {
    103                 this.pager = new Pager { pageIndex = int.Parse( pageIndex), pageSize = int.Parse( pageSize) };
    104             }
    105             if (!string.IsNullOrEmpty(sortField))
    106             {
    107                 this.sort = new SortItem { sortField = sortField, sortOrder = sortOrder };
    108             }
    109             if (!string.IsNullOrEmpty(filter))
    110             {
    111                 this.queryItems = JsonHelper.Json2Object<List<QueryItem>>(filter);
    112             }
    113            
    114         }
    115         //生成常量表达式
    116         private ConstantExpression GetValueConstant(string value, Type type)
    117         {
    118             string typeName = type.Name.ToLower();
    119             ConstantExpression rtn = null;
    120             switch (typeName)
    121             {
    122                 case "int32":
    123                     int intValue;
    124                     if (!int.TryParse(value, out intValue))
    125                     {
    126                         rtn = Expression.Constant(false);
    127                     }
    128                     else
    129                     {
    130                         rtn = Expression.Constant(intValue);
    131 
    132                     }
    133                     break;
    134                 case "string":
    135 
    136                     rtn = Expression.Constant(value);
    137                     break;
    138                 case "float":
    139                     float fValue;
    140                     if (!float.TryParse(value, out fValue))
    141                     {
    142                         rtn = Expression.Constant(false);
    143                     }
    144                     else
    145                     {
    146                         rtn = Expression.Constant(fValue);
    147 
    148                     }
    149                     break;
    150                 case "single":
    151                     Single sgValue;
    152                     if (!Single.TryParse(value, out sgValue))
    153                     {
    154                         rtn = Expression.Constant(false);
    155                     }
    156                     else
    157                     {
    158                         rtn = Expression.Constant(sgValue);
    159 
    160                     }
    161                     break;
    162                 case "decimal":
    163                     decimal dcValue;
    164                     if (!decimal.TryParse(value, out dcValue))
    165                     {
    166                         rtn = Expression.Constant(false);
    167                     }
    168                     else
    169                     {
    170                         rtn = Expression.Constant(dcValue);
    171 
    172                     }
    173                     break;
    174                 case "double":
    175                     double dbValue;
    176                     if (!double.TryParse(value, out dbValue))
    177                     {
    178                         rtn = Expression.Constant(false);
    179                     }
    180                     else
    181                     {
    182                         rtn = Expression.Constant(dbValue);
    183 
    184                     }
    185                     break;
    186                 case "datetime":
    187                     DateTime dateValue;
    188                     if (!DateTime.TryParse(value, out dateValue))
    189                     {
    190                         rtn = Expression.Constant(false);
    191                     }
    192                     else
    193                     {
    194                         rtn = Expression.Constant(dateValue);
    195 
    196                     }
    197                     break;
    198 
    199                 default:
    200                     rtn = Expression.Constant(false);
    201                     break;
    202 
    203 
    204 
    205 
    206             }
    207             return rtn;
    208 
    209         }
    210 
    211 
    212         //生成列表常量表达式  实现 In ('a','b') 
    213         private ConstantExpression GetValueListConstant(string value, Type type)
    214         {
    215             string typeName = type.GenericTypeArguments.Length == 0 ? type.Name : type.GenericTypeArguments[0].Name;
    216             ConstantExpression rtn = null;
    217             switch (typeName.ToLower())
    218             {
    219                 case "int32":
    220                     int intValue;
    221                     string[] arrInt = value.Split(',');
    222                     List<int> dlInt = new List<int>();
    223                     foreach (string a in arrInt)
    224                     {
    225                         if (int.TryParse(a, out intValue))
    226                         {
    227                             dlInt.Add(intValue);
    228                         }
    229 
    230                     }
    231                     if (dlInt.Count == 0)
    232                     {
    233                         rtn = Expression.Constant(false);
    234 
    235                     }
    236                     else
    237                     {
    238                         rtn = Expression.Constant(dlInt);
    239                     }
    240 
    241                     break;
    242                 case "string":
    243                     List<string> dlStr = value.Split(',').ToList();
    244                     if (dlStr.Count == 0)
    245                     {
    246                         rtn = Expression.Constant(false);
    247 
    248                     }
    249                     else
    250                     {
    251                         rtn = Expression.Constant(dlStr);
    252                     }
    253                     break;
    254 
    255 
    256                 default:
    257                     rtn = Expression.Constant(false);
    258                     break;
    259 
    260 
    261 
    262 
    263             }
    264             return rtn;
    265 
    266         }
    267 
    268 
    269         /// <summary>
    270         /// 根据前台查询字段自动生成Lambad(支持=,like,between,in 查询)
    271         /// </summary>
    272         /// <returns></returns>
    273         public Expression<Func<TEntity, bool>> BulidWhere()
    274         {
    275             Type type = typeof(TEntity);
    276             string key = "";
    277             string value = "";
    278             string match = "";
    279             string innerkey = "";
    280             ParameterExpression instance = Expression.Parameter(type);
    281             BinaryExpression result = Expression.Equal(Expression.Constant(true), Expression.Constant(true));
    282             if (queryItems == null) return Expression.Lambda<Func<TEntity, bool>>(result, instance);
    283             foreach (var item in queryItems)
    284             {
    285                 key = item.key;
    286 
    287                 value = item.value;//.ToLower();
    288                 if (string.IsNullOrEmpty(value)) continue;
    289                 match = item.match.ToLower();
    290                 innerkey = !string.IsNullOrEmpty(item.innerkey) ? item.innerkey : key;
    291                 PropertyInfo propertyInfo = type.GetProperty(innerkey);
    292                 var proFullType = propertyInfo.PropertyType;
    293                 Type propertyType = proFullType.GenericTypeArguments.Length == 0 ? proFullType : proFullType.GenericTypeArguments[0];
    294                 var valueExpression = match == "in" ? this.GetValueListConstant(value, propertyType) : this.GetValueConstant(value, propertyType);
    295                 MemberExpression propertyExpression = Expression.Property(instance, propertyInfo);
    296                 if (proFullType.Name.Contains("Nullable"))
    297                 {
    298                     propertyExpression = Expression.Property(propertyExpression, "Value");
    299                 }
    300                 var falseExpression = (Expression)Expression.Constant(false);
    301                 if (valueExpression.Value.ToString() == "False")
    302                 {
    303 
    304                     result = Expression.And(result, falseExpression);
    305                     continue;
    306                 }
    307                 switch (match)
    308                 {
    309                     case "=":
    310                         result = Expression.And(result, Expression.Equal(propertyExpression, valueExpression));
    311                         break;
    312                     case "like":
    313                         if (propertyType == typeof(string))
    314                         {
    315                             var like = Expression.Call(propertyExpression, typeof(string).GetMethod("Contains"), valueExpression);
    316                             result = Expression.And(result, like);
    317                         }
    318                         else
    319                         {
    320                             result = Expression.And(result, falseExpression);
    321 
    322                         }
    323                         break;
    324                     case "in":
    325                         if (propertyType == typeof(string) || propertyType == typeof(Int32))
    326                         {
    327                             var inExp = Expression.Call(valueExpression, valueExpression.Type.GetMethod("Contains", new Type[] { propertyType }), propertyExpression);
    328                             result = Expression.And(result, inExp);
    329                         }
    330                         else
    331                         {
    332                             result = Expression.And(result, falseExpression);
    333 
    334                         }
    335 
    336                         break;
    337                     case "from":
    338 
    339                         if (propertyType.IsValueType)
    340                         {
    341 
    342                             var from = Expression.GreaterThanOrEqual(propertyExpression, valueExpression);
    343                             result = Expression.And(result, from);
    344                         }
    345                         else
    346                         {
    347                             result = Expression.And(result, falseExpression);
    348 
    349                         }
    350                         break;
    351                     case "to":
    352                         if (propertyType.IsValueType)
    353                         {
    354 
    355                             var from = Expression.LessThanOrEqual(propertyExpression, valueExpression);
    356                             result = Expression.And(result, from);
    357                         }
    358                         else
    359                         {
    360                             result = Expression.And(result, falseExpression);
    361 
    362                         }
    363                         break;
    364                 }
    365             }
    366             var lambda = Expression.Lambda<Func<TEntity, bool>>(result, instance);
    367             return lambda;
    368 
    369         }
    370     }
    371 }
    View Code

    这一套自动查询支持对应sql的 In,=,Like ,Between 查询,原理上也支持Not Like, Not In但是一般给用户的查询不会用到这些查询。

    扩展EF框架的 DBSet:
     1 namespace App.PageBase.Query
     2 {
     3     // 摘要: 
     4     //     提供一组用于查询实现 System.Linq.IQueryable<T> 的数据结构的 static(在 Visual Basic 中为 Shared)方法。
     5     public static class DbSet
     6     {
     7         /// <summary>
     8         /// 按QueryBulider自动生成 过滤,排序,分页
     9         /// </summary>
    10         /// <typeparam name="T"></typeparam>
    11         /// <param name="qb"></param>
    12         /// <param name="query"></param>
    13         /// <returns></returns>
    14         public static IQueryable<T> Query<T>(this DbSet<T> qb, QueryBulider<T> query) where T : class,new()
    15         {
    16 
    17             var IQ = qb.Where(query.BulidWhere());
    18             if (query.sort == null && query.pager != null)
    19             {
    20                 throw new Exception("列表分页时必须指定排序字段");
    21             }
    22 
    23             Type type = typeof(T);
    24             var callWhere = IQ.Expression;
    25             if (query.sort != null)
    26             {
    27                 var sortFieldProperty = type.GetProperty(query.sort.sortField);
    28                 var instance =Expression.Parameter(type);
    29                 var sortFieldExpression = Expression.Property(instance, sortFieldProperty);
    30                 string OrderName = query.sort.sortOrder;
    31                 if (OrderName.ToLower() == "desc")
    32                 {
    33                     OrderName = "OrderByDescending";
    34                 }
    35                 else
    36                 {
    37                     OrderName = "OrderBy";
    38                 }
    39 
    40                 Expression.Lambda(sortFieldExpression, instance);
    41                 callWhere = Expression.Call(typeof(Queryable), OrderName, new Type[] { type, sortFieldProperty.PropertyType }, callWhere, Expression.Lambda(sortFieldExpression, instance));
    42             }
    43             if (query.pager != null)
    44             {
    45                 IQ = IQ.Provider.CreateQuery<T>(callWhere).Skip(query.pager.pageIndex * query.pager.pageSize).Take(query.pager.pageSize);
    46             }
    47 
    48             return IQ;
    49 
    50         }
    51 
    52 
    53     }
    View Code

       后台页面调用:

       var  queryBulider = new QueryBulider<UserInfo>(Request.Form);

       var dl = db.Set<UserInfo>().Query(queryBulider);

    当然前台js组件不同,前台的封装就不一样。MiniUi我是这样弄的。

    ///组合查询条件

    function GetQueryFormData(formId) {
    var data = [];
    if (!formId) formId = "queryForm";
    var form = new mini.Form("#" + formId);
    var fields = form.getFields();
    var arr = [];
    for (var i = 0; i < fields.length; i++) {
    var item = {};
    item["key"] = fields[i].id;
    item["value"] = fields[i].value;
    item["match"] = fields[i].match;
    item["innerkey"] = fields[i].innerkey;
    arr.push(item);
    }


    return arr;
    }

    ///查询事件

    function search() {
    var grid = mini.get("datagrid1");
    var query = GetQueryFormData();
    var json = mini.encode(query);
    grid.load({ filter: json });
    }





  • 相关阅读:
    在HTML中使用JavaScript
    七层网络模型
    JS执行机制
    继承
    变量作用域
    跨域
    ES6-Promise
    回调函数
    2019.3.9笔试
    CSS3新特性
  • 原文地址:https://www.cnblogs.com/colorlife/p/4742165.html
Copyright © 2020-2023  润新知