1

我知道,如果您使用 Linq-to-objects 执行交叉连接,则内部序列会针对外部序列的每个元素迭代一次。

以下代码演示了 的多次迭代ints2

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main()
        {
            var ints1 = Ints1();
            var ints2 = Ints2();

            var test = from i in ints1
                       from j in ints2
                       select i*j;

            foreach (var i in test)
                Console.WriteLine(i);
        }

        private static IEnumerable<int> Ints1()
        {
            Console.WriteLine("Starting  Ints1()");

            for (int i = 0; i < 5; ++i)
                yield return i;

            Console.WriteLine("Ending Ints1()");
        }

        private static IEnumerable<int> Ints2()
        {
            Console.WriteLine("Starting Ints2()");

            for (int i = 0; i < 5; ++i)
                yield return i;

            Console.WriteLine("Ending Ints2()");
        }
    }
}

我的问题是这样的:

如果您在 Linq-to-SQL 中执行相同类型的查询,它会优化为 SQLCROSS JOIN吗?还是会多次评估内部序列(或做其他事情)?

(我几乎可以肯定它会被优化,但在搜索“网络”后,我没有找到任何关于此的结论性文档。)


[编辑]

我只是想提一下我问这个问题的原因。

Resharper如果您迭代 IEnumerable 两次,通常会警告您,但如果您使用嵌套执行交叉连接(例如在我上面的示例代码中) ,它不会警告您。from

我想知道为什么它没有警告您,并认为这可能是由于以下两个原因之一:

要么是疏忽,要么不需要,因为多重枚举对于嵌套来说不是问题,from因为它变成了 Linq-to-SQL 中的高效操作。我想是后一个原因。

现在您可能想知道是否Resharper仍应发出警告,因为 Linq-to-objects多次枚举内部序列 - 但我想这不那么严重。

此外,我实际上从未在数据库上执行过这样的交叉连接(我也不打算这样做),但我已经在 Linq-to-objects 中使用了它们。

4

1 回答 1

4

Linq-to-SQL 将 linq 查询转换为在数据库端运行的 T-SQL 。

例如,如果你写:

from i in myContext.Table1
from j in myContext.Table2
select new {i,j}

Linq-to-SQL 会将其转换为类似于以下内容的 T-SQL 查询:

SELECT * 
FROM Table1, Table2

然后它将通过只对结果集进行一次迭代来为生成的匿名类型对象提供服务。

希望这是有道理的。

于 2013-04-19T08:46:10.387 回答