Join LINQ到实体在实例而不是id上连接会生成SQL

Join LINQ到实体在实例而不是id上连接会生成SQL,join,linq-to-entities,Join,Linq To Entities,有人能解释一下,为什么按实体而不是id联接会生成一些非常难看的sql,而实际上它在概念上做的事情与您认为的是一样的吗?e、 g 凭身份证 产生 FROM [COMPANY] AS [Extent1] INNER JOIN [ADDRESS] AS [Extent2] ON [Extent1].[CONTACT_ADDRESS_ID] = [Extent2].[CONTACT_ADDRESS_ID] 举例来说 from companyDirector in CompanyDirecto

有人能解释一下,为什么按实体而不是id联接会生成一些非常难看的sql,而实际上它在概念上做的事情与您认为的是一样的吗?e、 g

凭身份证

产生

FROM  [COMPANY] AS [Extent1]
    INNER JOIN [ADDRESS] AS [Extent2] ON [Extent1].[CONTACT_ADDRESS_ID] = [Extent2].[CONTACT_ADDRESS_ID]
举例来说

from companyDirector in CompanyDirectors
join contactAddress in ContactAddresses
  on companyDirector.ContactAddress equals contactAddress
select new {companyDirector, contactAddress}
产生

FROM  [COMPANY] AS [Extent1]
INNER JOIN [ADDRESS] AS [Extent2] ON  EXISTS (SELECT 
    1 AS [C1]
    FROM    ( SELECT 1 AS X ) AS [SingleRowTable1]
    LEFT OUTER JOIN  (SELECT 
        [Extent3].[CONTACT_ADDRESS_ID] AS [CONTACT_ADDRESS_ID]
        FROM [ADDRESS] AS [Extent3]
        WHERE [Extent1].[CONTACT_ADDRESS_ID] = [Extent3].[CONTACT_ADDRESS_ID] ) AS [Project1] ON 1 = 1
    LEFT OUTER JOIN  (SELECT 
        [Extent4].[CONTACT_ADDRESS_ID] AS [CONTACT_ADDRESS_ID]
        FROM [ADDRESS] AS [Extent4]
        WHERE [Extent1].[CONTACT_ADDRESS_ID] = [Extent4].[CONTACT_ADDRESS_ID] ) AS [Project2] ON 1 = 1
    WHERE [Project1].[CONTACT_ADDRESS_ID] = [Extent2].[CONTACT_ADDRESS_ID]
)

在我看来,这是非常低效的,迫使你进入身份证途径。为什么它要做两次左连接,更不用说一次了???

我不能说出ADO.NET团队的想法或代码。尽管如此,我看到了两个可能的问题:

  • 很可能,
    ContractAddresses
    中的基础表中的
    Id
    字段,或者可能仅在实体模型中,无法定义为主键。我有点怀疑这是个问题,但值得仔细检查
  • 实际上,
    equals
    关键字可能没有很好的方法来比较联接中两个对象之间的相等性。在快速的web搜索中,我没有找到
    equals
    用于比较的确切内容,但让我相信
    equals
    GetHashCode
    方法都涉及其中(即使不涉及组合键)。如果您只是使用默认的
    object.Equals
    继承方法,Linq提供程序必须以某种方式找出引用等式,我想这可能会导致一些奇怪的结果

  • 不过,我确实喜欢@Craig Stuntz在评论中提出的解决方案。此外,您可能需要为较长的查询获取一个执行计划,以查看它是否真的像看上去的那样糟糕;查询优化器可能比代码所显示的做得更好。

    最后,对于我来说,EF仍然缺乏在广阔的世界中执行所需的成熟度和功能。因此,我放弃了它,转而选择了NHibernate,它可以生成简单漂亮且经过优化的SQL。

    即使这个问题非常好,我们在这里也很难回答。这是ADO.NET团队的问题。如果ADO.NET团队没有订阅这些关键字,他们需要在某人的十字准线中:)FWIW,我不会写任何一个。我将从companyDirector中的companyDirector从companyDirector中的contactAddress写入
    。ContactAddresses选择新的{companyDirector,contactAddress}
    ,它应该可以正常工作,并且不需要了解DB架构即可写入。
    FROM  [COMPANY] AS [Extent1]
    INNER JOIN [ADDRESS] AS [Extent2] ON  EXISTS (SELECT 
        1 AS [C1]
        FROM    ( SELECT 1 AS X ) AS [SingleRowTable1]
        LEFT OUTER JOIN  (SELECT 
            [Extent3].[CONTACT_ADDRESS_ID] AS [CONTACT_ADDRESS_ID]
            FROM [ADDRESS] AS [Extent3]
            WHERE [Extent1].[CONTACT_ADDRESS_ID] = [Extent3].[CONTACT_ADDRESS_ID] ) AS [Project1] ON 1 = 1
        LEFT OUTER JOIN  (SELECT 
            [Extent4].[CONTACT_ADDRESS_ID] AS [CONTACT_ADDRESS_ID]
            FROM [ADDRESS] AS [Extent4]
            WHERE [Extent1].[CONTACT_ADDRESS_ID] = [Extent4].[CONTACT_ADDRESS_ID] ) AS [Project2] ON 1 = 1
        WHERE [Project1].[CONTACT_ADDRESS_ID] = [Extent2].[CONTACT_ADDRESS_ID]
    )