选择导航属性为null的条目的最佳方法

时间:2013-02-16 15:19:52

标签: c# linq entity-framework

我遇到了一些性能问题。我有以下数据库模型。 Model

我希望选择Entity2中Entity1中没有外键的所有条目,换句话说导航属性必须为null。

我已经提出了以下LINQ查询context.Entity2Set.Where(x => x.Entity1 == null);并且它可以正常运行,但速度很慢。所以我想知道是否有更好(更快)的方式(除了索引之外)来选择条目。

最后,我想从Entity4中选择条目,因此性能是一个问题。

2 个答案:

答案 0 :(得分:2)

您正在查询关系中的主体(Entity2),而不是依赖关系(Entity1)。这意味着外键位于表Entity1中,生成的SQL查询不仅仅是对表Entity2中列值的查询。为了获得所需的结果,SQL查询必须(通过LEFT OUTER JOIN)加入两个表。

如果是一对多关系,您的查询就像:“获取所有没有订单商品的订单。”仅通过检查Order表无法实现这一点,因为外键位于表OrderItem中,并且查询必须连接两个表。实际上,在此示例中,可以通过索引表OrderItem中的外键列来改进查询的性能。

不幸的是,在您的示例中,您不能通过索引列来改进查询,因为您具有一对一的关系(不是一对多关系)。由于EF的一对一关系始终是共享主键关联,因此表Entity1中的外键同时是其主键Id

这意味着您的外键列已经被索引 - 即通过表Entity1中的聚簇主键索引。

生成的SQL查询如下:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[OtherColumn] AS [OtherColumn]
FROM   [dbo].[Entity2] AS [Extent1]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent3] ON [Extent2].[Id] = [Extent3].[Id]
WHERE [Extent3].[Id] IS NULL

正如您所看到的,这些表由索引的Id列连接在一起。第二个冗余的LEFT OUTER JOIN是实体框架SQL生成中的一个缺陷,它对EF< 5.0。我不确定它是否在EF> = 5.0中解决。我不知道它对于查询性能是否真的重要,因为该行通过同一列将表连接到自身,所以我希望SQL查询优化器能够识别它并忽略执行计划中的行。

本质上:您的LINQ查询很好,即使不是通过向列中添加任何其他索引也无法提高性能。

但是,我建议的是找出 真正慢的东西。它确实是SQL查询,还是从LINQ查询到SQL的转换,还是它可能是返回结果集的对象实现等等?我要做的第一步是将生成的SQL查询粘贴到SQL Server Management Studio中,看看性能如何。即使您不更改LINQ查询,也可能有其他机会来提高性能。

答案 1 :(得分:0)

你说过

  

没有索引

但对于这个问题,这将是一个错误。索引几乎可以立即找到所有空引用。