zoukankan      html  css  js  c++  java
  • 强大的拉姆表达式转Sql 类库

    使用场景

    1、Lambda to sql 一直是ORM中最难的功能之一,如果有现成的解析库那么自已写一个ORM难度将大大降低

    2、通过Lambda作为KEY进行缓存操作,特别是仓储模式想要拿到表达式进行通用查询缓存 则需要用到表达式解析

    3、学习爱好者,如果能够较深入的理Lambda如何去解成Sql,那么你对Lambda的理解将会更上一个层次,而不仅仅在使用上

    优点

    SqlSugar除了有自带的ORM功能,还是一款强大的拉姆达解析器  ,并且是市场上独有 的拉姆达转Sql类库 

    SqlSugar不仅小巧并且性能非常的好,毫不逊色于Dapper 甚至更加的优秀  ,至于性能别看其他人的测评 非常不靠谱,自个用了才知道,自个测了才知道

    1、高性能  表达式解析速度远超EF 

    2、功能非常完整 ,并且是产品级的解析类库,支持各种模式的解析

    3、小巧你只要引用SqlSugar一个DLL就能使用 解析各种数据库 、支持Sql函数 、支持常用原生函数

    安装

    .NET CORE / NET5   Nuget SqlSugarCore

    .NET 4.5   Nuget SqlSugar 

    .NET 4.0 Nuget SqlSuagr 4.x

    入门

    我们先来看一下例子

    static void Main(string[] args)
    {
     var age = 11;
     Expression<Func<Test, bool>> exp = a => a.id == age; //表达式
     SqlServerExpressionContext expContext = new SqlServerExpressionContext();//创建解析对象
     expContext.Resolve(exp, ResolveExpressType.WhereSingle);//开始解析
     var value = expContext.Result.GetString();//( [id] = @id0 )
     var pars = expContext.Parameters;// @id:11
    }  

     下面是调试结果:

     通过上面的例子就能够完美的将表达式转换成Sql语句

    教程案例

    1、如何创建 ExpressionContext 解析对象

     我们可以通过SqlSugar.DbType进行区分数据库 并且进行实例化

    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("不支持");

     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 )

    我们在写一个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+'%') 

    bool类型的解析是ORM解析的难点中的难点,情况多种多样

    Expression<Func<DataTestInfo2, bool>> exp = it => it.Bool1&&it.Bool1;
    SqlServerExpressionContext expContext = new SqlServerExpressionContext();
    expContext.Resolve(exp, ResolveExpressType.WhereSingle);
    var value = expContext.Result.GetString();
    var pars = expContext.Parameters;
    //( ( [Bool1]=1 ) AND ( [Bool1]=1 ) )

    多样化的bool解释的支持

    Expression<Func<Student, bool>> exp = it =>true&& it.Name != null;
    ExpressionContext expContext = new ExpressionContext();
    expContext.Resolve(exp, ResolveExpressType.WhereSingle);
    var value = expContext.Result.GetString();
    var pars = expContext.Parameters;
    //(( 1 = 1 ) AND( [Name] IS NOT NULL ))

    多表查询的支持,在多表查询中我们是需要加前缀的比如 我们想要 it.id 而不是id

      Expression<Func<Student, bool>> exp = it => (it.Id > 1 && it.Name != name || it.Id == 1) || it.Name == WhereConst.name;
      ExpressionContext expContext = new ExpressionContext();
      expContext.Resolve(exp, ResolveExpressType.WhereMultiple);
      var value = expContext.Result.GetString();
      var pars = expContext.Parameters;
    //(((( [it].[Id] > @Id0 ) AND ( [it].[Name] <> @Name1 )) OR ( [it].[Id] = @Id2 )) OR ( [it].[Name] = @Name3 ))

    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] 
    Expression<Func<Student, School, object>> exp = (it, school) => new { Name = "a", Id = it.Id / 2, SchoolId = school.Id };
    ExpressionContext expContext = new ExpressionContext();
    expContext.IsSingle = false;
    expContext.Resolve(exp, ResolveExpressType.SelectMultiple);
    var selectorValue = expContext.Result.GetString();
    // @constant0 AS [Name] , ( [it].[Id] / @Id1 ) AS [Id] , [school].[Id] AS [SchoolId] 

    3、字段名称的解析

    例如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])

    4、Sql函数的支持 

    Expression<Func<Student, bool>> exp = it => (it.Name.Contains("a")? 1:2)==1;
    SqlServerExpressionContext expContext = new SqlServerExpressionContext();
    expContext.Resolve(exp, ResolveExpressType.WhereSingle);
    var value = expContext.Result.GetString();
    var pars = expContext.Parameters;
    //(( CASE  WHEN  ([Name] like '%'+@MethodConst0+'%')  THEN @MethodConst1  ELSE @MethodConst2 END ) = @Const3 )

    支持的C#函数:

    .ToString  .Contains  .Length

    .ToLower  .ToUpper  .ToSubstring 

    .Equals    .HasValue  .Replace

    .EndsWith  .StartsWith  .Trim

    .HasValue  .Value  .AddDay  .Date

    和常用的Convert.ToInt32等等 

    SqlFunc.函数

    SqlFunc函数下面包含了大量SQL函数  

     SqlFunc.IF(st.Id > 1)
         .Return(st.Id)
         .ElseIF(st.Id == 1)
         .Return(st.SchoolId).End(st.Id) //等于Case when

    5、其它功能

    5.1 支持特性比如我表名和实体名不一样我们也可以实现

    SqlServerExpressionContext expContext = new SqlServerExpressionContext();
    expContext.MappingTables.Add(typeof(Student).Name,"OA_STUDENT")

    列名也非常容易

    SqlServerExpressionContext expContext = new SqlServerExpressionContext();
    expContext.MappingColumns.Add("Id","ID",typeof(Student).Name)

    5.2 支持子查询

    Expression<Func<Test, bool>> exp = a => SqlFunc.Subqueryable<Sutdent>().Where(it => it.testId == a.id).Select(it => it.id) == 1);
    var expContext = new SqlServerExpressionContext();
     expContext.Resolve(exp, ResolveExpressType.WhereSingle);
    var value = expContext.Result.GetString();
    var pars = expContext.Parameters;

    6、自已动手创建ORM

    通上面的学习你们想写出下面的语法应该相当容易了 

     var oneClass = db.Queryable<Order, OrderItem, Custom>((o, i, c) => o.Id == i.OrderId&& o.CustomId == c.Id))
    .Where(o=>o.id==1) 
    .Where((o,i)=>i.xx==1) 
    .OrderBy(o=>o.Id)
    .Select((o,i,c)=> new ViewOrder
     {
              Id=SqlFunc.GetSelfAndAutoFill(o.Id),// o.*
              CustomName=c.Name   //[c].[Name] AS [CustomName]
    }).ToList()

    实现上面的功能 总共用到Where的解析、列的解析和Select的解析

    1、下面3个用到Where的解析

    (o, i, c) => o.Id == i.OrderId&& o.CustomId == c.Id)
     o=>o.id==1
    (o,i)=>i.xx==1

     2、下面1个用到列的解析

    o=>o.Id

     3、下面1个用到Select的解析

    (o,i,c)=> new ViewOrder
     {
              Id=SqlFunc.GetSelfAndAutoFill(o.Id),// o.*
              CustomName=c.Name   //[c].[Name] AS [CustomName]
    }

      

    源码下载:

    你们的赞或者你们的 star 就是 开源者的动力 ,开源不容易和气生财 

    https://github.com/sunkaixuan/SqlSugar     

    彩蛋:

    下一篇文章 我会介绍如何使用 SqlSugar 实现WebFirst模式开发代码,领先CodeFirst和DbFirst的设计和开发理念,也我十多年开发经验的汇总

  • 相关阅读:
    [arXiv18]更快的基于非二叉化自底向上策略的转移系统成分句法分析
    [AAAI18]面向序列建模的元多任务学习
    [COLING18]两种成分句法分析的局部特征模型
    [ACL18]基于RNN和动态规划的线性时间成分句法分析
    成分句法分析综述
    [NAACL16]RNN文法
    [TACL17]基于中序转移的成分句法分析
    K-摇臂赌博机算法与实现
    关于JVM案例分析(四)
    关于JVM案例分析(三)
  • 原文地址:https://www.cnblogs.com/sunkaixuan/p/14088197.html
Copyright © 2011-2022 走看看