0


【动态表达式】.NET开源 ORM 框架 SqlSugar 系列


🎖️动态表达式的应用场景和优势 :

‌ 🔸动态查询‌:通过动态表达式,可以在运行时根据不同的条件构建查询语句,适用于 复杂 的查询逻辑和 灵活 的查询需求。

🔸‌减少硬编码‌:避免 了在代码中硬编码 SQL 语句,减少了维护成本和出错的可能性。

🔸‌提高开发效率‌:开发者可以专注于 业务逻辑 的实现,而不是低层次的数据库操作。

🔸‌增强安全性‌:动态表达式可以 减少SQL注入 等安全风险,因为 参数化查询 可以自动处理。

🎯**动态表达式 **可以方便动态表达式实现业务处理 ,当我们的业务场景需要N多聚合查询条件时,这个功能尤为重要。


1、动态表达式 📒

1.1 用例 🔖

//用例1:连写
Expression<Func<Order, bool>> exp = Expressionable.Create<Order>() //创建表达式
              .AndIF(p > 0, it => it.Id == p)
              .AndIF(name != null, it => it.Name == name && it.Sex==1)
              .ToExpression();//注意 这一句 不能少
               
var list = db.Queryable<Order>().Where(exp).ToList();//直接用就行了不需要判段 null和加true
   
 
//用例2:分开写法
var expable= Expressionable.Create<Order>();
...逻辑
expable.And(it.xx==x);
...逻辑
expable.And(it.yy==y);
...逻辑
var exp=expable.ToExpression();//要用变量 var exp=
db.Queryable<Order>().Where(exp).ToList()//直接用就行了不需要判段 null和加true
 
//用例3:多表查询
var exp=Expressionable.Create<Order,T2,T3>()
         .And((x,y,z)=>z.id==1).ToExpression();//注意 这一句 不能少
          
          
//技巧 WhereIF 有时候更方便
var list=db.Queryable<T>()
.WhereIF(p>0,it=>it.p==p)
.WhereIF(y>0,it=>it.y==y)
.ToList()

1.2 拓展用例 🔖

我们可以用动态表达式实现 In ( name like 1, name like2 , name like3 ...) in 的模糊查询

var names= new string [] { "a","b"};
Expressionable<Order> exp = Expressionable.Create<Order>();
foreach (var item in names)
{
    exp.Or(it => it.Name.Contains(item.ToString()));
}
var list= db.Queryable<Order>().Where(exp.ToExpression()).ToList();

生成的Sql

SELECT [Id],
        [Name],
        [Price],
        [CreateTime],
        [CustomId]
     FROM [Order]  
     WHERE (
            ([Name] like '%'+ CAST(@MethodConst0 AS NVARCHAR(MAX))+'%') OR 
             ([Name] like '%'+ CAST(@MethodConst1 AS NVARCHAR(MAX))+'%')
         )

1.3 Queyable.Or 🔖

我们可以通过 .Where().Where 实现多个 AND 如果想实现 OR 就只能借助动态表达式实现, query.or 让表达式中可以用 OR 。

 var exp = Expressionable.Create<Order>()
              .And(it => it.Id == 1)
              .Or(it=>it.Id==100 )
              .ToExpression();//注意 这一句 不能少
               
var list= db.Queryable<Order>().Where(exp).ToList();
//Sql
//   where id=1 or id=100

1.4 去掉1==1 🔖

var ex=Expressionable.Create<Student03>()
    .AndIf(id>0,it=>it.Id==id).ToExpression();
//如果一个条件没有有,你又不想生成1=1,可以结合whereif实现
var isEmpty = ((ex as LambdaExpression).Body as ConstantExpression)?.Value?.Equals(true)==true;
var students = db.Queryable<Student03>()
    .WhereIF(!isEmpty, ex).ToList();

2、字符串 To 表达式 📒

📤 5.1.4.107-preview14+

 //程序启动时配置
  StaticConfig.DynamicExpressionParserType = typeof(DynamicExpressionParser);
  StaticConfig.DynamicExpressionParsingConfig = new ParsingConfig()//用到SqlFunc需要配置这个属性
            {
                CustomTypeProvider = new SqlSugarTypeProvider()//这个类需要自已定义下面有
            };
             
  
 //导航属性动态
 var list3 = db.Queryable<UnitPerson011>().Where("it", $"SqlFunc.Exists(it.Address.Id)").ToList();
  
 //普通条件动态
 var list4 = db.Queryable<UnitPerson011>().Where("it", $"it.Name={"a"}").ToList();
  
 //动态类+动态条件
 var list5=db.QueryableByObject(typeof(UnitPerson011)).Where("it", $"it.Address.Id=={1}").ToList();
  
  
 //扩展类型          
 public class SqlSugarTypeProvider : DefaultDynamicLinqCustomTypeProvider
        {
            public override HashSet<Type> GetCustomTypes()
            {
                var customTypes = base.GetCustomTypes();
                customTypes.Add(typeof(SqlFunc));//识别SqlFunc
                return customTypes;
            }
      }
         
/****参数说明****/
  
//硬编码  Id>1
FormattableString str = $"it.Id>1";
   
//固定字段+参数化变量 Id>@p=1
FormattableString str2 = FormattableStringFactory.Create("it.Id>{0}",1);
   
//动态字段+参数化变量 Id>@p=1
var p="it.Id";
FormattableString str2 = FormattableStringFactory.Create(p+">{0}",1);

✅ 该功能和 表格查询 可以互补 。

3、表达式 To Sql 📒

🧮如果你们技术团队只让你用 Ado ,你们也可以把 SqlSugar 当成表达式解析器 。

    var expContext = new SqlServerExpressionContext();
    Expression<Func<IOrder, bool>> exp = it => it.id==1;
    expContext.Resolve(exp, ResolveExpressType.WhereSingle);
    var wheresql = expContext.Result.GetString();
     
    var pars = expContext.Parameters;
    db.Queryable<Order>().Where(wheresql).AddParameters(pars).ToList();

3.1 声名表达式解析器 🔖

ExpressionContext expContext=null;
switch (dbtype)
{
case DbType.MySql:
expContext = new MySqlExpressionContext();
break;
case DbType.SqlServer:
expContext = new SqlServerExpressionContext();
break;
case DbType.Sqlite:
expContext = new SqliteExpressionContext();
break;
case DbType.Oracle:
expContext = new OracleExpressionContext();
break;
case DbType.PostgreSQL:
expContext = new PostgreSQLExpressionContext();
break;
case DbType.Dm:
expContext = new DmExpressionContext();
break;
case DbType.Kdbndp:
expContext = new KdbndpExpressionContext();
break;
default:
throw new Exception("不支持");

3.2 Where条件的解析 🔖

🧮基本和写 EF 一样常用的都会支持。

Expression<Func<DataTestInfo2, bool>> exp = it => it.Bool2== b.Value;
expContext.Resolve(exp, ResolveExpressType.WhereSingle);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//( [Bool2] = @Bool20 ) //WhereSingle 没有别名 it

🧮我们在写一个 Like 的例子。


Expression<Func<Student, bool>> exp = it => it.Name.Contains(schoolData.Name);
ExpressionContext expContext = new ExpressionContext();
expContext.Resolve(exp, ResolveExpressType.WhereMultiple);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//([it].[Name] like '%'+@MethodConst0+'%') //WhereMultiple解析后会有别我 [it].

3.3 Select的解析 🔖

✅支持实体类解析、查询单个字段解析、匿名对象解析。

Expression<Func<DataTestInfo2,DataTestInfo2>> exp=it=>new DataTestInfo2(){Bool1=it.Bool1,Bool2=it.Bool2};
ExpressionContext expContext = new ExpressionContext();
expContext.IsSingle = false;
expContext.Resolve(exp, ResolveExpressType.SelectSingle);
var selectorValue = expContext.Result.GetString();
var pars = expContext.Parameters;
//[Bool1] AS [Bool1] , [Bool2] AS [Bool2]

3.4 字段名称的解析 🔖

🧮例如 orderby(it=>it.Name) 像这种我们就需要拿到Name

Expression<Func<Student, object>> exp = it => it.Name;
ExpressionContext expContext = GetContext();
expContext.Resolve(exp, ResolveExpressType.FieldSingle);
var selectorValue = expContext.Result.GetString();
//Name

🧮统计单个字段

Expression<Func<Student, object>> exp = it =>SqlFunc.AggregateAvg(it.Id);
ExpressionContext expContext = GetContext();
expContext.Resolve(exp, ResolveExpressType.FieldMultiple);
var selectorValue = expContext.Result.GetString();
//AVG([it].[Id])

3.5 更改列名 🔖

var data=new MappingColumn() 
                { DbColumnName = "OrderId", 
                 PropertyName = "Id", 
                 EntityName = "Order" };
expContext.MappingColumns.Add(data);
Expression<Func<Order, bool>> exp = it => it.Id== 1;
expContext.Resolve(exp, ResolveExpressType.WhereSingle);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//( [OrderId] = 1)

4、常见错误 📒

4.1 拼接超出1000报错 🔖

🧮方案1:

较高版本支持 List.Any 和 List.All

.Where(it=>List.Any(s=>s.id==it.id&&s.name==it.id2))//高版本支持  OR
.Where(it=>List.All(s=>s.id==it.id&&s.name==it.id2))//高版本支持  AND

🧮方案2:

底层是用 递归解析 表达式,递归受到限制 超过1000 就会报错 ,我们可以通过设置 线程 最大堆栈解决。

 List<Order> list = null;
    var t=new System.Threading.Thread(async () =>
    {
        var expable = SqlSugar.Expressionable.Create<Order>();
        for (int i = 0; i < 1000; i++)
        {
            expable.Or(it => it.Id == i && it.Id == i);
        }
        var getOrderBy = db.Queryable<Order>().Where(expable.ToExpression()).ToListAsync();
        var x = 0;
 
    },int.MaxValue);//设置线程栈
    t.Start();
    Thread.Sleep(1000);//设置等待时间保证这个 线程执行完

** .NET开源 ORM 框架 SqlSugar 系列**

  1. 【开篇】.NET开源 ORM 框架 SqlSugar 系列
  2. 【入门必看】.NET开源 ORM 框架 SqlSugar 系列
  3. 【实体配置】.NET开源 ORM 框架 SqlSugar 系列
  4. 【Db First】.NET开源 ORM 框架 SqlSugar 系列
  5. 【Code First】.NET开源 ORM 框架 SqlSugar 系列
  6. 【数据事务】.NET开源 ORM 框架 SqlSugar 系列
  7. 【连接池】.NET开源 ORM 框架 SqlSugar 系列
  8. 【查询目录】.NET开源 ORM 框架 SqlSugar 系列
  9. 【查询基础】.NET开源 ORM 框架 SqlSugar 系列
  10. 【排序用法】.NET开源 ORM 框架 SqlSugar 系列
  11. 【分组去重】.NET开源 ORM 框架 SqlSugar 系列
  12. 【联表查询】.NET开源 ORM 框架 SqlSugar 系列
  13. 【导航查询】.NET开源 ORM 框架 SqlSugar 系列
  14. 【子查询】.NET开源 ORM 框架 SqlSugar 系列
  15. 【嵌套查询】.NET开源 ORM 框架 SqlSugar 系列
  16. 【配置查询】.NET开源 ORM 框架 SqlSugar 系列
  17. 【并集查询】.NET开源 ORM 框架 SqlSugar 系列
  18. 【树型查询】.NET开源 ORM 框架 SqlSugar 系列
  19. 【表格查询】.NET开源 ORM 框架 SqlSugar 系列

❤️关注、👍点赞、🔶收藏 💞

标签: .net 开源 windows

本文转载自: https://blog.csdn.net/mss359681091/article/details/144312331
版权归原作者 Microi风闲 所有, 如有侵权,请联系我们删除。

“【动态表达式】.NET开源 ORM 框架 SqlSugar 系列”的评论:

还没有评论