【问题标题】:Difference using joins or navigation properties in EF在 EF 中使用连接或导航属性的差异
【发布时间】:2018-07-06 23:10:15
【问题描述】:

我正在学习 EF,并试图了解何时使用哪种类型的查询。

例如这个查询:

From fe In Processes.Where(Function(process) CBool(process.Type = 21 And 
                                            process.State = 0 And
                                            process.VDat > #2017/01/01# And
                                            process.ProcessAdresses.Any(Function(adr) adr.AdrNr = "0201") And
                                            process.ProcessPorisitions.Any(Function(pp) pp.ArtID = 200)))

将返回 Type=21State=0Vdat>01.01.2017 中的所有 processes,其中 processAdressAdrNr=0201 和 positionArtId=200。 这里使用了导航属性并且必须启用延迟加载。 (我认为,因为需要加载相关数据,并且在访问导航道具时会加载)

现在我可以使用连接来表达相同的查询:

From fe In Processes.Where(
            Function(process) CBool(
                process.Art = 215 And
                process.State = 0 And
                process.VDat > #2017/01/01#))
     Join adr In ProcessAdresses.Where(
             Function(adr) adr.AdrNr = "020107")
         On fe.VID Equals vadr.VID
     Join pp In ProcessPorisitions.Where(
             Function(pp) pp.ArtID = 20004993)
         On fe.VID Equals vpos.VID
     Group  By fe Into Group
     Select fe

这里没有使用导航道具。

我试图使用 LinqPad 测量/分析性能,但我只能看到创建的 SQL 查询中的差异,不费吹灰之力......

所以我的问题是:

  • 查询一种方式与查询另一种方式的主要区别是什么?
  • 在使用其中一种时是否有任何规则可遵循?
  • 在这种情况下或一般的 SQL 查询中,我如何才能弄乱性能?

【问题讨论】:

    标签: sql database performance entity-framework linq


    【解决方案1】:

    查询一种方式与查询另一种方式的主要区别是什么?

    联接更难阅读且更容易出错。 EG 第二个查询返回的数据和第一个一样吗?

    在使用其中一种时有什么规则要遵循吗?

    尽可能使用导航属性。

    我怎样才能在这种情况下或一般的 SQL 查询中弄乱性能?

    不正确的连接会导致性能下降,复杂的 LINQ 查询会导致异常复杂的 SQL。此外,急切加载过多的相关实体可能会导致昂贵的查询。

    【讨论】:

    • 最后一点没有解决连接与导航属性的问题。当然,在导航属性甚至不可用的情况下,可以通过连接进行过于复杂的查询,但这是一个不同的问题。使用导航属性也完全可以预先加载太多数据。
    • 不正确的连接是唯一与导航属性与连接问题相关的连接,因为导航属性已预先连接了连接列。其他与“或一般的 SQL 查询部分”相关
    • 这个问题太宽泛了。我喜欢这个问题,所以我试着把它缩小到标题中的问题,忽略了这个小部分,而不是 VTC 太宽泛了。此外,无论如何都应该修复不正确的连接,而不是因为或性能。
    • 是的,我的问题就像@gertArnold 所说的那样,集中在join vs nav props 问题上。因此,如果我理解正确的话,我应该尽可能使用导航道具和延迟加载/急切加载。然后是关于性能和何时使用延迟加载与急切加载的问题,但这是一个不同的问题......
    【解决方案2】:

    查询一种方式与查询另一种方式的主要区别是什么?

    看看你的代码就足够了。使用导航属性使代码更容易理解和更好地维护。此外,显式连接容易出错。加入错误的 ID 属性很容易(我见过这种情况)。最后,如果您有更多类似的查询,它会导致重复代码。

    在使用其中一种时有什么规则要遵循吗?

    指南DRY 就是其中之一。见上文。

    我怎样才能在这种情况下或一般的 SQL 查询中弄乱性能?

    这可能是规则(指南)的唯一例外。非强制性实体的导航属性将被翻译为外部连接。外连接的性能可能比内连接差。因此,当性能至关重要时当空引用应该从最终结果中过滤掉时,您可以诉诸显式连接语句,覆盖导航属性。

    另请参阅:Don't use Linq's Join. Navigate!

    【讨论】:

    • 导航属性也往往会导致大量嵌套查询,在某些情况下,我发现这可能会导致冗余连接,这是昂贵的。最好的策略可能是始终为您编写的每个 LINQ 查询检查生成的 SQL。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多