【发布时间】:2018-12-18 11:21:21
【问题描述】:
情况:假设我们正在执行一个连接两个内存列表的 LINQ 查询(因此不涉及 DbSet 或 SQL 查询生成),并且该查询还有一个 where 子句。此where 仅过滤原始集合中包含的属性(查询的from 部分)。
问题: linq 查询解释器是否优化了这个查询,因为它首先执行where,然后再执行join,不管我是在前面还是后面写where join? – 因此它不必对以后不包含的元素执行连接。
示例:例如,我有一个categories 列表,我想加入一个products 列表。但是,我只对category 和ID 1 感兴趣。无论我是否编写,linq 解释器是否在内部执行完全相同的操作:
from category in categories
join prod in products on category.ID equals prod.CategoryID
where category.ID == 1 // <------ below join
select new { Category = category.Name, Product = prod.Name };
或
from category in categories
where category.ID == 1 // <------ above join
join prod in products on category.ID equals prod.CategoryID
select new { Category = category.Name, Product = prod.Name };
以前的研究: 我已经看到this question 但 OP 作者 stated 他/她的问题仅针对生成 SQL 的非内存案例。我对 LINQ 在内存中的两个列表上执行连接非常感兴趣。
更新:这不是 "Order execution of chain linq query" 问题的重复,因为引用的问题显然是指数据库集,而我的问题明确解决了非数据库场景。 (此外,虽然相似,但我不是在这里询问基于导航属性的包含,而是关于“连接”。)
Update2:虽然非常相似,但这也不是 "Is order of the predicate important when using LINQ?" 的重复,因为我明确询问内存中的情况,我看不到明确解决这种情况的引用问题。此外,这个问题有点老了,我实际上对 .NET Core 上下文中的 linq 感兴趣(2012 年不存在),所以我更新了这个问题的标签以反映第二点。
请注意:关于这个问题,我的目标是 linq 查询解释器是否会在后台以某种方式优化此查询,并希望获得对一段文档或源代码的参考,以说明如何这是由 linq 完成的。我不对诸如“没关系,因为两个查询的性能大致相同”之类的答案感兴趣。
【问题讨论】:
-
是的。没有翻译。 LINQ to Objects 查询按原样执行,不会转换为其他内容。
Where()是一个迭代器,它遍历输入并返回与谓词匹配的任何项目。对于the full framework 和.NET Core,您可以直接查看源代码以了解其实现方式 -
如果你想要可以忍受的性能,你不应该加入这样的内存列表。您将进行 M*N 比较。您应该创建字典或哈希集来查找具有公共键的条目
-
@SeM 请参阅我的观点,说明为什么这不是重复的。您的第二个链接非常接近,但没有明确引用内存中的连接。但是,您的评论说服了我在说明我对 dotnet core 上下文中的 linq 感兴趣时提出了尖锐的问题。
标签: c# linq join .net-core where