过滤时 Include() 的顺序对性能有影响吗?
Does the order of Include()s when filtering have an impact on performance?
这工作正常,我假设它加载所有实体与所有 Foo
和 Bar
children,然后根据 Foo
过滤结果值:
var baz = "sillystring";
context.Entities
.Include(e => e.Foo)
.Include(e => e.Bar)
.Where(e.Foo == baz)
.Select(e.Bar)
.ToList();
那么,如果是这样的话,这是一个有用的优化吗?首先进行过滤,然后 Bar
children 只包含实体的子集?
var baz = "sillystring";
context.Entities
.Include(e => e.Foo)
.Where(e.Foo == baz)
.Include(e => e.Bar) // moved to after the filter
.Select(e.Bar)
.ToList();
...另外,EF 是否足够聪明,知道当我使用 .Select(e.Bar)
时必须包含 Bar
?
事实是,在这种情况下它真的无关紧要,因为两个 Includes
都被忽略了。您可以删除它们,查询将产生完全相同的 SQL 和结果。
这是因为 Include
仅在应用于查询结果根实体(如果有)时才有效。这意味着它们在投影 (Select
) 查询到匿名/DTO/ViewModel 等类型时被忽略。只考虑直接返回实体类型的查询,正如我之前所说,如果 Include
s 从该实体类型开始。
很多人误解了 Include
的目的。使用导航属性进行过滤、排序、分组、选择等的查询的正确运行根本不需要它们。它们的全部目的是 Load Related Entities.
在您的示例中,唯一有效的包含是 Bar
的导航属性,它们必须插入 Select(e => e.Bar)
之后。它们的顺序并不重要,Select
和 Include
之间的 LINQ 运算符也不重要,因为它们不会更改查询结果类型。
这工作正常,我假设它加载所有实体与所有 Foo
和 Bar
children,然后根据 Foo
过滤结果值:
var baz = "sillystring";
context.Entities
.Include(e => e.Foo)
.Include(e => e.Bar)
.Where(e.Foo == baz)
.Select(e.Bar)
.ToList();
那么,如果是这样的话,这是一个有用的优化吗?首先进行过滤,然后 Bar
children 只包含实体的子集?
var baz = "sillystring";
context.Entities
.Include(e => e.Foo)
.Where(e.Foo == baz)
.Include(e => e.Bar) // moved to after the filter
.Select(e.Bar)
.ToList();
...另外,EF 是否足够聪明,知道当我使用 .Select(e.Bar)
时必须包含 Bar
?
事实是,在这种情况下它真的无关紧要,因为两个 Includes
都被忽略了。您可以删除它们,查询将产生完全相同的 SQL 和结果。
这是因为 Include
仅在应用于查询结果根实体(如果有)时才有效。这意味着它们在投影 (Select
) 查询到匿名/DTO/ViewModel 等类型时被忽略。只考虑直接返回实体类型的查询,正如我之前所说,如果 Include
s 从该实体类型开始。
很多人误解了 Include
的目的。使用导航属性进行过滤、排序、分组、选择等的查询的正确运行根本不需要它们。它们的全部目的是 Load Related Entities.
在您的示例中,唯一有效的包含是 Bar
的导航属性,它们必须插入 Select(e => e.Bar)
之后。它们的顺序并不重要,Select
和 Include
之间的 LINQ 运算符也不重要,因为它们不会更改查询结果类型。