LinqToSql -由CONCAT (UNION)生成的SQL

本文关键字:SQL UNION CONCAT LinqToSql | 更新日期: 2023-09-27 18:03:51

简单地说,有没有办法强制LinqToSql生成链式concats而不嵌套UNION ALL语句?

的例子:

a.Concat(b).Concat(c)

的结果在语义上类似:

SELECT * FROM (
    SELECT * FROM A
    UNION ALL 
    SELECT * FROM B
)
UNION ALL
SELECT * FROM C

如果我能说服它这样做的话,它会更容易读/更可取:

SELECT * FROM A
UNION ALL
SELECT * FROM B
UNION ALL
SELECT * FROM C

我明白为什么它这样做(我甚至不确定这两件事是完全相同的语义),但有什么办法使这种情况发生吗?这将使我们生成的查询更容易阅读和调试。

LinqToSql -由CONCAT (UNION)生成的SQL

从LINQ生成的SQL不是设计为可读的,所以我认为没有办法做到这一点。这很好,我同意。这是我对像Dapper这样的微orm概念感兴趣的原因之一,这样我就可以自己编写SQL了。

我在连接大型自动生成的查询表集时遇到了问题,因为生成的sql查询的嵌套行为太深,sql无法处理。我通过以类似二叉树的方式将条目连接起来解决了这个问题,如下所示:

public static IQueryable<T> BinaryConcatenation<T>(this IEnumerable<IQueryable<T>> queries)
{
    var count = queries.Count();
    var firsthalf = queries.Take(count / 2).ToArray();
    var secondhalf = queries.Skip(count / 2).ToArray();
    if (firsthalf.Length == 0 || secondhalf.Length == 0) return queries.Aggregate((src, next) => src.Concat(next));
    var first = BinaryConcatenation(firsthalf);
    var second = BinaryConcatenation(secondhalf);
    return first.Concat(second);
}

这样生成的SQL嵌套深度会大大降低(log(n)?)。