【问题标题】:Simple Linq query has duplicated join against same table?简单的 Linq 查询对同一个表重复了连接?
【发布时间】:2011-05-27 11:17:22
【问题描述】:

(来自 Julia Lerman 的新实体框架书中的一个示例。)我有一个包含两个表的数据库,即联系人和地址。 Contact 表有一个 ContactID (int),还有名字、姓氏等。Address 表有一个 ContactID,还有城市、州、邮编等。

这是一个简单的 LINQ 查询:

var addressGraphQuery = from a in context.Addresses.Include("Contact")
                        orderby a.Contact.LastName, a.Contact.FirstName
                        select a;

从 SQL Profiler 中,我看到以下内容:

SELECT 
    [Extent1].[addressID] AS [addressID], 
    [Extent1].[City] AS [City], 
    [Extent1].[StateProvince] AS [StateProvince], 
    -- etc
    [Extent3].[ContactID] AS [ContactID1], 
    [Extent3].[FirstName] AS [FirstName], 
    [Extent3].[LastName] AS [LastName], 
    -- etc
FROM   [dbo].[Address] AS [Extent1]
INNER JOIN [dbo].[Contact] AS [Extent2] ON [Extent1].[ContactID] = [Extent2].[ContactID]
LEFT OUTER JOIN [dbo].[Contact] AS [Extent3] ON [Extent1].[ContactID] = [Extent3].[ContactID]
ORDER BY [Extent2].[LastName] ASC, [Extent3].[FirstName] ASC

它与联系人表连接两次!为什么?有没有简单的方法可以防止这种情况发生?


谜团加深。当我删除 orderby 时,连接消失了。当我设置context.ContextOptions.LazyLoadingEnabled = false 时,连接不会消失。

这里也有类似的问题:

Too Many Left Outer Joins in Entity Framework 4?

我会看看有没有更高的力量我可以问...

【问题讨论】:

  • 我已合并您创建的所有三个帐户。请注册,它会为我(和其他模组)节省一些时间。另外,为了将来参考,cmets 用于评论,answers 用于回答。检查faq,欢迎来到SO。

标签: linq entity-framework join


【解决方案1】:

感谢您报告此问题。是的,预计不会同时看到这两个联接。这是一个已在当前(尚未发布)位中修复的错误。在当前位中,相同的查询产生:

SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[ContactId] AS [ContactId],
...
[Extent2].[Id] AS [Id1],
..
[Extent2].[FirstName] AS [FirstName],
[Extent2].[LastName] AS [LastName]
FROM  [dbo].[Address] AS [Extent1]
INNER JOIN [dbo].[Contact] AS [Extent2] ON [Extent1].[ContactId] = [Extent2].[Id] ORDER BY [Extent2].[LastName] ASC, [Extent2].[FirstName] ASC

我玩了一下显示,即使在 4.0 上,这也只会在关系为 1:many 时发生,0..1:many 似乎很好。

谢谢,

卡蒂·伊塞瓦
实体框架开发人员
微软

【讨论】:

  • 我刚刚在 NuGet 中出现的最新版本中尝试过这个,我仍然看到霍布斯描述的查询。有这方面的更新吗?
  • 实际上,这个问题已经在最新的 6 月 CTP - blogs.msdn.com/b/adonet/archive/2011/06/30/… 中修复了 - (但还没有在 NuGet 版本中)
  • 这是在 4.3.1 版本中修复还是仅在 EF5 中修复?
  • 我对 1:1 或 1:0..1 连接有同样的问题。最初它似乎没有影响,但最终数据增长导致问题。通过添加一个愚蠢的.Where(x => x.table1 != null && x.table2 != null) 条件,它导致 dup 连接被插入到 SQL 能够更好地处理并返回性能的子查询中。很奇怪。
  • @Kati lceva ,EF 6.1.3 中仍然存在此错误
【解决方案2】:

霍布斯, 我不知道您为什么要同时获得内部和外部联接。包括对查询做了奇怪的事情。我已将您的问题提交给团队,看看这是否是预期的(尽管如此糟糕),以及是否有办法缓解它。有问题的查询只是一个示例,用于演示如果您进入绑定,您可以在查询中使用实体引用导航属性。

【讨论】:

  • EF 6.1.3 中仍然存在此错误
【解决方案3】:

我倾向于使用 lambda 语法,所以我可能是错的,但我认为您会发现您希望 order by 子句的第二部分实际上是“then by”。

例如

var query = context.Addresses.Include("Contact")
                   .OrderBy(a => a.Contact.LastName)
                   .ThenBy(a => a.Contact.FirstName)

【讨论】:

  • 嗯,实际上,我可能是错的!见:stackoverflow.com/questions/298725/linq-multiple-order-by
  • 是的,你错了 =) ThenBy() 应该相当于 Linq 的 orderby 中的第二个排序顺序。
  • 不,我认为@Reddog 是对的。如果您查看 SQL,它有 ORDER BY [Extent2].[LastName] ASC, [Extent3].[FirstName] ASC。当只需要一个时,按两个不同的查询(Extent2、Extent3)排序。这是订单。我觉得这个答案是对的。 (我认为)
  • 查看msdn.microsoft.com/en-us/vcsharp/aa336756 的“ThenBy - Simple”示例。它将 orderby 与两个表达式一起使用,用逗号分隔。此语法等价于 OrderBy().ThenBy()。
  • 为了完整起见,我尝试了OrderBy().ThenBy(),仍然有重复的join =(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-14
  • 1970-01-01
  • 2015-01-23
  • 2023-03-19
  • 1970-01-01
相关资源
最近更新 更多