起因,想测试下查询语句的生成,按以下逻辑代码示例

var query = rep.GetLambdaQuery().Take(100);
var join = query.Select(b => new { a1 = b.Id, a2 = b.F_String }).Join<TestEntityItem>((a, b) => a.a1 == b.TestEntityId);//第一次关联
var join2 = join.Select((a, b) => new { a3 = a.a1, a4 = b.Name })
.Join<TestEntity>((a, b) => a.a3 == b.Id);//第二次关联
join2.Select((a, b) => new
{
a.a4,
b.Id
});

这里为多层嵌套关联,是一个比较常见到场景,根据逻辑意义和语法支持,多数ORM都能实现这个查询

对应sql为

select
t4.[a4],
t1.[Id]
from
(
select
t2.[a1] as a3,
t3.[Name] as a4
from
(
select
t1.[Id] as a1,
t1.[F_String] as a2
from
[TestEntity] t1
LIMIT 0, 100
) t2
Inner join [TestEntityItem] t3 on t2.a1 = t3.[TestEntityId]
) t4
Inner join [TestEntity] t1 on t4.a3 = t1.[Id]

测试了最近看到的几个ORM

Chloe

var query = getContext().Query<TestEntity>().Take(100);
var join = query.Select(b => new { a1 = b.Id, a2 = b.F_String }).Join<TestEntityItem>(JoinType.InnerJoin, (a, b) => a.a1 == b.TestEntityId);
var query3 = join.Select((a, b) => new { a3 = a.a1, a4 = b.Name })
.Join<TestEntity>(JoinType.InnerJoin, (a, b) => a.a3 == b.Id).Select((a, b) => new
{
a.a4,
b.Id
});
var sql = query3.ToString();
Console.WriteLine($"{GetType().Name}: {sql}");

输出为

SELECT
[TestEntityItem].[Name] AS [a4],
[TestEntity0].[Id]
FROM
(
SELECT
[TestEntity].[Id] AS [a1],
[TestEntity].[F_String] AS [a2]
FROM
[TestEntity] AS [TestEntity]
LIMIT
100 OFFSET 0
) AS [T]
INNER JOIN [TestEntityItem] AS [TestEntityItem] ON [T].[a1] = [TestEntityItem].[TestEntityId]
INNER JOIN [TestEntity] AS [TestEntity0] ON [T].[a1] = [TestEntity0].[Id]

在第一次关联生成的还正常,第二次关联就不对了

FastFramework

var query = getDb().Query<TestEntity>().Take(100);
var join = query.Select(b => new { a1 = b.Id, a2 = b.F_String }).InnerJoin<TestEntityItem>((a, b) => a.a1 == b.TestEntityId);
var query2 = join.Select((a, b) => new { a3 = a.a1, a4 = b.Name })
.InnerJoin<TestEntity>((a, b) => a.a3 == b.Id).Select((a, b) => new
{
a.a4,
b.Id
});
var sql = query2.ToSqlString();
Console.WriteLine($"{GetType().Name}: {sql}");

输出

SELECT [p1].[a4] AS [a4],[p2].[Id] AS [Id] FROM [TestEntity] [p1]
INNER JOIN [TestEntityItem] [p2] ON ( [p1].[a1] = [p2].[TestEntityId] )
INNER JOIN [TestEntity] [p2] ON ( [p1].[a3] = [p2].[Id] ) LIMIT 0,100

完全不对

FreeSql

db.Aop.CurdAfter += (s, e) =>
{
Console.WriteLine($"{GetType().Name}: {e.Sql}");
};
var query = db.Select<TestEntity>().Take(100);
var query2 = query.WithTempQuery(b => new { a1 = b.Id, a2 = b.F_String });
var query3 = query2.FromQuery(db.Select<TestEntityItem>()).InnerJoin((a, b) => a.a1 == b.TestEntityId);
var query4 = query3.WithTempQuery((a, b) => new { a3 = a.a1, a4 = b.Name }).FromQuery(db.Select<TestEntity>()).InnerJoin((a, b) => a.a3 == b.Id); ;
var result = query4.WithTempQuery((a, b) => new
{
a.a4,
b.Id
}).ToList();

输出

SELECT *
FROM (
SELECT a."a4", b."Id"
FROM (
SELECT a."a1" "a3", b."Name" "a4"
FROM (
SELECT a."Id" "a1", a."F_String" "a2"
FROM "TestEntity" a
limit 0,100 ) a
INNER JOIN "TestEntityItem" b ON a."a1" = b."TestEntityId" ) a
INNER JOIN "TestEntity" b ON a."a3" = b."Id" ) a

基本正确,少了as语法,看着有些怪异

SqlSugar

var query = db.Queryable<TestEntity>().Take(100);
var query2 = query.Select(b => new { a1 = b.Id, a2 = b.F_String });
var query3 = query2.InnerJoin<TestEntityItem>((a, c) => a.a1 == c.TestEntityId);
var query4 = query3.Select((a, c) => new { a3 = a.a1, a4 = c.Name })
// .InnerJoin<TestEntity>((d, e) => d.a3 == e.Id).Select((d, e) => new
//{
// d.a4,
// e.Id
//})
;
var sql = query4.ToSqlString();
Console.WriteLine($"{GetType().Name}: {sql}");

注意第二次关联注释掉了,如果加上直接异常

System.Exception:“中文提示 : Join TestEntity 错误, 请把 (d,e)=> 改成 (a,c,TestEntity )=>
English Message : Join TestEntity error , Please change (d,e)=> to (a,c,TestEntity )=>.”

第一次关联输出

SELECT
`a`.`a1` AS `a3`,
`b`.`Name` AS `a4`
FROM
(
SELECT
*
FROM
(
SELECT
`Id` AS `a1`,
`F_String` AS `a2`
FROM
`TestEntity`
LIMIT
0, 100
) MergeTable
) `a`
Inner JOIN `TestEntityItem` `b` ON (`a`.`a1` = `b`.`TestEntityId`)

革命尚未成功,同志仍须努力

喜闻乐见最新的ORM查询BUG,看看有没你关注的的更多相关文章

  1. 灵活使用 SQLAlchemy 中的 ORM 查询

    之前做查询一直觉得直接拼 SQL 比较方便,用了 SQLAlchemy 的 ORM 查询之后,发现也还可以,还提高了可读性. 这篇文章主要说说 SQLAlchemy 常用的 ORM 查询方式,偏实践. ...

  2. Django 源码小剖: Django ORM 查询管理器

    ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.从 ...

  3. Django ORM 查询管理器

    Django ORM 查询管理器 ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言 ...

  4. Spring+SpringMVC+MyBatis+easyUI整合基础篇(八)mysql中文查询bug修复

    写在前面的话 在测试搜索时出现的问题,mysql通过中文查询条件搜索不出数据,但是英文和数字可以搜索到记录,中文无返回记录.本文就是写一下发现问题的过程及解决方法.此bug在第一个项目中点这里还存在, ...

  5. ORM查询条件

    模板: from django.db import models class Article(models.Model): title = models.CharField(max_length=20 ...

  6. Django之ORM查询复习与cookie

    ORM查询总结: models.Book.objects.filter(**kwargs): querySet [obj1,obj2] models.Book.objects.filter(**kwa ...

  7. ORM( ORM查询13种方法3. 单表的双下划线的使用 4. 外键的方法 5. 多对多的方法 ,聚合,分组,F查询,Q查询,事务 )

    必知必会13条 <1> all(): 查询所有结果 <2> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或 ...

  8. Python学习---ORM查询之基于对象的正向/反向/聚合/分组/Q/F查询

    ORM查询之基于对象的正向查询与反向查询 对象形式的查询 # 正向查询 ret1=models.Book.objects.first() print(ret1.title) print(ret1.pr ...

  9. ORM查询练习

    ORM查询练习 Django ORM  ORM查询的练习题 ORM代码 from django.db import models # Create your models here. class Pu ...

  10. Django框架 之 ORM查询操作详解

    Django框架 之 ORM查询操作详解 浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Py ...

随机推荐

  1. 前后端分离实现注册+登录(Vue3.0 + Django3.2)

    博客地址:https://www.cnblogs.com/zylyehuo/ 一.使用 vite+webstorm 搭建 Vue 环境,构建前端 1.结构树 2.main.js import { cr ...

  2. quarkus依赖注入之三:用注解选择注入bean

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<quarkus依赖注入> ...

  3. K8S | Config应用配置

    绕不开的Config配置: 一.背景 在自动化流程中,对于一个应用来说,从开发阶段的配置管理,到制作容器镜像,再到最后通过K8S集群发布为服务,整个过程涉及到的配置非常多: 应用环境:通常是指代码层面 ...

  4. GitOps 与 DevOps:了解关键差异,为企业做出最佳选择

    在软件开发领域,GitOps 和 DevOps 是加强协作和实现软件交付流程自动化的重要技术.虽然这两种模式都旨在提高软件开发生命周期的效率,但它们的核心原则和实施方式却各不相同. 本篇文章将帮助您了 ...

  5. 《高级程序员 面试攻略 》RocketMQ 如何保证顺序性

    RocketMQ 提供了一种称为顺序消息的机制来确保消息的顺序性.下面是一些关键的方法和概念: 1. 顺序消息:顺序消息是指在发送和消费过程中,消息按照特定的顺序进行处理.RocketMQ 通过将消息 ...

  6. Web开发框架 WebBuilder 9 发布

    WebBuilder 是一款强大,全面和高效的Web开发框架 .基于浏览器的集成开发环境,智能化的设计,能轻松完成常规桌面应用和面向手机等的移动应用开发.高效.稳定和可扩展的特点,适合复杂企业级应用的 ...

  7. 在centos7.X下安装tomcat – 东凭渭水流

    发布于 14 分钟前  1 次阅读 1.下载tomcat,并用工具将tomcat传输到linux中 mkdir /oopt/tomcat 2.解压tomcat文件 tar -zxvf apache-t ...

  8. 每日一库:gosec

    gosec 是一个用于在 Go 代码中查找安全问题的开源工具,它可以帮助发现可能的漏洞和潜在的安全风险.以下是关于 gosec 的详细介绍: 1. 工具概述: gosec 是一个静态分析工具,用于扫描 ...

  9. python 获取本周 ,上周,本月,上月,本季,上季,今年, 去年的第一天和最后一天

    import datetime from datetime import timedelta now = datetime.datetime.now()# 获取当前月的天数 month = 2days ...

  10. Adobe全家桶PS、PR、AU等2022正版永久有效,无需破解直接安装就能用

    [Adobe全家桶]已经亲测绝对好用,下载地址: 关注我的wx公众号"奋斗在IT"回复1013获取下载地址.