强大的 Lambda 式转 Sql 类库 - SqlSugar 隐藏功能之 Lambda

喜欢吃鱼的青年 2020-12-08 09:47:27 ⋅ 1004 阅读

使用场景

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://gitee.com/sunkaixuan/SqlSugar


全部评论: 0

    我有话说:

    挖一挖那些让公司网站瘫痪SQL“终结者”

    一条慢查询会造成什么后果?之前我一直觉得不就是返回数据会慢一些么,用户体验变差? 其实远远不止,我经历过几次线上事故,有一次就是由一条 SQL 慢查询导致。 那次是一条 SQL 查询耗时达到 2

    HeidiSQL 11.1 发布,功能强大数据库客户端软件

    HeidiSQL 11.1 现已发布。HeidiSQL 是一个功能非常强大数据库客户端软件,采用 Delphi 开发,支持 Windows 操作系统。支持 MySQL、MariaDB

    Excelize -Go 开源项目中唯一支持复杂样式 XLSX 文件

    Go 语言编写一个用来操作 Office Excel 文档

    推荐一款功能强大,开源免费H5可视化编辑器

    H5-Dooring 是一款功能强大,开源免费H5可视化页面配置解决方案,致力于提供一套简单方便、专业可靠、无限可能H5落地页最佳实践。技术栈以react为主, 后台采用nodejs开发. 预览

    TeamCity 2020.2.2 发布,功能强大持续集成工具

    TeamCity 2020.2.2 发布了。TeamCity 是一款功能强大持续集成工具,覆盖服务器端和客户端。它提供一系列特性可以让团队快速实现持续集成:IDE 工具集成、各种消息通知

    2018常用JavaScript

    9个非常有用Javascript来加速你开发。

    SQL 模板神器

    SqlTemplate - MyBatis SqlTemplate - MyBatis 是sql模板引擎,主要解决动态拼接sql字符串 。原理是比较简单,把模板内容构建成完成xml,这样

    Spring 5 WebFlux 响应开发示例

    Spring 5 已经大力支持了响应开发模式,引入响应框架叫做 Spring WebFlux。

    CrateDB 4.3.1 发布,分布式 SQL 数据库

    CrateDB 4.3.1 预发布。Crate 是一个开源大规模可伸缩数据存储系统,无需任何系统管理需求。提供强大搜索功能。用于存储各种表格数据、非结构化数据和二进制对象。并可通过 SQL

    8 种最坑 SQL 错误用法,你有没有踩过坑?

    编写复杂SQL语句要养成使用 WITH 语句习惯。简洁且思路清晰SQL语句也能减小数据库负担 。

    「小米技术」Soar一键优化工具--SQL优化和改写自动化工具

    SOAR(SQL Optimizer And Rewriter)是一个对SQL进行优化和改写自动化工具。由小米人工智能与云平台数据库团队开发与维护。

    谷歌AI创造了AI,比人类编写更加强大

    AI也能自行繁衍了。根据外媒报道。谷歌AI系统AutoML创造了一个AI——NASNet,测试后发现,NASNet表现已经比人类工程师撰写AI更为强大。ML是机器学习(machine

    代码整洁道:Lombok 使用

    Lombok项目是一种自动接通你编辑器和构建工具一个Java。不用再一次写额外getter或者equals方法。

    PowerJob —强大分布式任务调度与计算框架

    PowerJob让您轻松完成作业调度与繁杂任务分布式计算。

    滴滴开源基于 React 移动端开发组件-Pile.js

    Pile.js 是滴滴开发基于 React 移动端开发组件。 轻量,易用,包含 52 个交互功能,支持多语言与自定义皮肤。可以非常轻松创建用户交互界面,让前端开发更专注于业务逻辑实现。

    Git中心工作流程

    Git中心工作流程

    Taro UI 2.0 发布:新增自定义主题功能,适配更多小程序

    Taro UI 发布已有半年,在此期间,不断完善组件功能和特性,新增了许多组件和小工具...

    Riot 5.3.1 发布,基于组件 UI

    Riot 5.3.1 现已发布。Riot 是一个简单而优雅基于组件 UI ,为所有现代浏览器带来了自定义组件,压缩文件大小仅有 6 KB,支持 FireFox、Chrome、Edge