zoukankan      html  css  js  c++  java
  • .NET 通用多条件动态参数查询方法 SqlSugar ORM

    通用查询用途

    一般我们Grid控件,会有很多条件传给后台,如果每个条件都写一个逻辑的话,那么工作量将非常大,所以通用查询功能是每个软件必备的,

    SqlSugar将通用查询封装到支持了树型条件,并且支持所有常用的操作,用SqlSugar或者不用SqlSugar的都可参参考一下

    1、简单多条件多动参数 

    创建数据库对象

     //创建数据库对象 SqlSugarClient   
     SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
     {
                ConnectionString = "Server=.xxxxx",//连接符字串
                DbType = DbType.SqlServer, //数据库类型
                IsAutoCloseConnection = true //不设成true要手动close
     });

    前台传的JSON格式   [{},{},{}]

     [
       {"FieldName":"id","ConditionalType":"0","FieldValue":"1"},
       {"FieldName":"name","ConditionalType":"0","FieldValue":"jack"}
     ]
    

    后台代码 

    //手动构造
    var conModels = new List<IConditionalModel>();
    conModels.Add(new ConditionalModel{ FieldName = "id",ConditionalType=ConditionalType.Equal,FieldValue="1"});
    conModels.Add(new ConditionalModel{ FieldName = "name",ConditionalType=ConditionalType.Equal,FieldValue="jack"});  
     
    //5.0.5.1 Json直接序列化
    var conModels= db.Context.Utilities.JsonToConditionalModels(json)  
     
    var student = db.Queryable<Student>().Where(conModels).ToList();
    //select * from Student where id=1 and name = 'jack'
    

    这种比较简单 多一条记录就多一个AND

    2、二级多条件动态参数

    这种模式对于表格查询已经够用了,支持到2级查询,并且AND OR都比较灵活了

    [ {"FieldName": "id","FieldValue": "1","ConditionalType": 10}, 
      {"FieldName": "id","FieldValue": null,"ConditionalType": 12}, 
      {
        "ConditionalList": [{
            "Key": 1,
            "Value": {
                "FieldName": "id",
                "FieldValue": "2",
                "ConditionalType": 0
            }
        }, {
            "Key": 0,
            "Value": {
                "FieldName": "id",
                "FieldValue": "2",
                "ConditionalType": 0
            }
        }]
    }]
    //5.0.5.1 Json直接序列化
    var whereList= db.Context.Utilities.JsonToConditionalModels(json);
    var list = db.Queryable<Order>().Where(whereList).ToList();
    

     生成的Sql: 

     WHERE   [id] <> @Conditid0   
        AND    [id]  IS NOT  NULL   
        OR     (   [id] = @Conditid10000   AND   [id] = @Conditid20000   )
    

    说明:ConditionalList 第一个Key为1 那么就会生成  Or( 条件 )

              ConditionalList 第一个Key为0 那么就会生成  And( 条件 )

              Key表式运算符:   And =0,  Or=1 

    例子1:ConditionalList  集合中 有3条记录 key =1 , key =0 ,key=1

    生成的Sql     OR(条件 AND 条件 OR条件)

    例子2:ConditionalList  集合中 有1条记录 key =1 

    生成的Sql     OR(条件)

    例子3:ConditionalList  集合中 有4条记录 key =0,key=1,key=1,key=1 

    生成的Sql     AND (条件 OR 条件 OR条件 OR 条件)

    这种模式只支持2级操作,需要更多层级就实现不了了

    3、树型动态条件 (请升级5.0.5.1)

    这种就比较强大了,一般用于表的公开API等操作,可以构造任何层级的条件 ,可以支持树型条件

    Key表式运算符:   And =0,  Or=1,  null=-1

     
    
    [{
        "ConditionalList": [{
            "Key": -1,
            "Value": {
                "FieldName": "id",
                "FieldValue": "2",
                "ConditionalType": 0
            }
        }, {
            "Key": 0,
            "Value": {
                "FieldName": "name",
                "FieldValue": "2",
                "ConditionalType": 0
            }
        }, {
            "Key": 0,
            "Value": {
                "ConditionalList": [{
                    "Key": -1,
                    "Value": {
                        "FieldName": "price",
                        "FieldValue": "1",
                        "ConditionalType": 0
                    }
                }, {
                    "Key": 0,
                    "Value": {
                        "FieldName": "CustomId",
                        "FieldValue": "1",
                        "ConditionalType": 0
                    }
                }]
            }
        }]
    }]
    

    生成的SQL:  

    WHERE  (   [id] = @Conditid10001   
    
          AND   [name] = @Conditname20001  
          AND(   [price] = @Conditprice10000   AND   [CustomId] = @ConditCustomId20000   )  )
    

      

    C#代码

    var conditionalModels = db.Context.Utilities.JsonToConditionalModels(json);
    var list = db.Queryable<Order>().Where(conditionalModels).ToList();  

     更多用例:https://www.donet5.com/Ask/9/14378

    3、操作符解释

    ConditionalTypek是一个枚举

    枚举枚举值描述
    Equal  0 等于
    Like  1 模糊查询
    GreaterThan  2 大于
    GreaterThanOrEqual  3 大于等于
    LessThan  4 小于
    LessThanOrEqual  5 小于等于
    In  6

    In操作

    正确格式   X,Y,Z 

    错误格式   'X','Y','z'

    NotIn  7 Not in操作 参数和in一样
    LikeLeft  8 左模糊
    LikeRight  9 右模糊
    NoEqual  10 不等于
    IsNullOrEmpty  11 是null或者''
    IsNot  12

    情况1   value不等于null

    字段<> x

    情况2   value等于null 

    字段 is not null

    NoLike  13 模糊查询取反
    EqualNull  14

    情况1   value不等于null

    字段= x

    情况2   value等于null 

    字段 is null

    InLike 15

    正确格式   X,Y,Z 

    错误格式   'X','Y','z'

    生在的Sql :  

     ( id like '%X%' or id like '%Y%' or id like '%Z%')

           

    4、列名验证或者转换

    需求1:实体和表中字段名称不一样的情况下,我们可以做下面转换

    foreach(var r in conModels)
    {        
       r.FieldName =db.EntityMaintenance.GetDbColumnName<Order>(r.FieldName );//这样就支持了用实体类中的属性作为参数
    }

    看文档:需求2:我要验证前端传过来的属性名和实体一样,列名虽然防注入,但是还是可以任意传,对于高安全级别项目加个验证更保险 

    https://www.donet5.com/Home/Doc?typeId=1202 

    5、类型转换

    比如PGSQL不支持字符串参数与INT类型相等,我们可以使用类型转换

    //SqlSugar自带的类型转换
    new ConditionalModel() { 
                    FieldName = "id", 
                    ConditionalType = ConditionalType.Equal, 
                    FieldValue = "1",
                    FieldValueConvertFunc=it=>SqlSugar.UtilMethods.ChangeType2(it,typeof(int)) 
                  }
    //自个实现类型转换                       
    new ConditionalModel()  { 
                    FieldName = "id", 
                    ConditionalType = ConditionalType.Equal, 
                    FieldValue = "1",
                    FieldValueConvertFunc=it=>Convert.ToInt32(it)) 
                   }
    

      

    6、多表查询去别名 

      

    List<IConditionalModel> conModels = new List<IConditionalModel>();
    conModels.Add(new ConditionalModel{ FieldName = "id", ConditionalType = ConditionalType.Equal,FieldValue="1"});
    
     //查询
     var list=db.Queryable<Order>()
              .LeftJoin<Custom>   ((o,i) => o.CustomId == cus.Id)
              .LeftJoin<OrderDetail> ((o,i,c) => o.Id == oritem.OrderId)
              .Select((o,i,c)=> new ViewOrder{ Id=o.Id CustomName=c.Name }) // 是一个新类 
              .MergeTable()//通过MergeTable处理下面的查询就不需要加上 (o,i,c) 的别名限制了  
              .Where(conModels)//因为Select通过Mergetable变成了一个新表,也就是说新表只有 id和CustomName 
              .ToList(); 

    7、未来计划

    未来会打算支持 Sql函数,真正做到所有的查询条件都能用  

      

     安装: Nuget SqlSugarCore

     源码: https://github.com/donet5/SqlSugar

  • 相关阅读:
    采用[ICONIX] 方法实践BLOG设计之一 [问题域建模]
    关于“三国众谋士”之IT从业可行性报告
    采用[ICONIX] 方法实践BLOG设计之二 [用例建模]
    NET框架中的 Decorator 和 Strategy 模式
    域模型向左走(充血),向右走(贫血)
    采用[ICONIX] 方法实践BLOG设计之五 [初步设计复核]
    Discuz!NT 缓存设计简析 [原创]
    Discuz!NT控件剖析 之 Tab 属性页 [原创: 附源码]
    没有银弹,但可以"扯蛋"
    Discuz!NT控件剖析 之 Button [原创: 附源码]
  • 原文地址:https://www.cnblogs.com/sunkaixuan/p/15732736.html
Copyright © 2011-2022 走看看