喜闻乐见最新的ORM查询BUG,看看有没你关注的

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

c# 复制代码
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为

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

c# 复制代码
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}");

输出为

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

c# 复制代码
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}");

输出

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

c# 复制代码
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();

输出

sql 复制代码
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

c# 复制代码
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}");

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

sql 复制代码
System.Exception:"中文提示 : Join TestEntity 错误, 请把 (d,e)=> 改成 (a,c,TestEntity )=> 
English Message : Join TestEntity error , Please change (d,e)=> to (a,c,TestEntity )=>."

第一次关联输出

sql 复制代码
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`)

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