【问题标题】:How do I avoid large generated SQL queries in EF when using Include()使用 Include() 时如何避免在 EF 中生成大量 SQL 查询
【发布时间】:2013-03-10 12:17:06
【问题描述】:

我正在使用 EF(dll 版本为 4.4)来查询数据库。该数据库包含几个包含课程信息的表格。当查看实际发送到数据库的内容时,我看到了一个庞大的、几乎 1300 行的 SQL 查询(由于它的大小,我不会在这里粘贴)。我在上下文中运行的查询如下所示:

entities.Plans
  .Include("program")
  .Include("program.offers")
  .Include("program.fees")
  .Include("program.intakes")
  .Include("program.requirements")
  .Include("program.codes")
  .Include("focuses")
  .Include("codes")
  .Include("exceptions")
  .Include("requirements")
where plans.Code == planCode
select plans).SingleOrDefault(); 

我想避免在从每个相关表中收集信息时返回服务器,但是对于如此大的查询,我想知道是否有更好的方法来做到这一点?

谢谢。

【问题讨论】:

  • 好吧,你正在做急切加载,你的查询试图一次获取所有数据,因此它很大。你到底认为那里有什么问题?其他选项是使用虚拟属性进行延迟加载,当您尝试访问它们时,EF 会在后台获取这些属性,但您确实指定不希望往返数据库。
  • 这里有一种类似的答案stackoverflow.com/questions/5521749/…
  • 我想我想知道我是否正确地看待这个问题。一个大查询与几个小查询,或者是否有更好的方法。
  • 您真的需要所有这些信息吗?你打算用它做什么?人类可能无法理解/处理它,但它可能对某些自动化处理有意义。我想我会问自己——如果我不使用 EF(创建这种查询很容易)但必须自己编写 SQL——我会创建这样的查询还是会找到我真正需要的东西并获取这些信息从数据库中提取并在需要时发送其他查询? (9 个连接是相当多的,但如果可以证明可能还可以)
  • 其他表格中的信息被汇总显示为课程信息的简短摘要,所以是的,我真的需要它。

标签: entity-framework entity-framework-4


【解决方案1】:

有点晚了,但是由于您的数据每天只更改一次,请考虑将您需要的所有内容放入索引视图中,并将此视图放入您的 EF 模型中。

【讨论】:

    【解决方案2】:

    您通常可以在 where 子句之后添加.Include()。这意味着您只会提取与您想要的信息相匹配的信息,看看这是否会减少您的查询。

    【讨论】:

    • 这没什么区别。我在 LINQPad 中运行查询,生成的 SQL 在两种情况下都是相同的。
    • after where 子句还是一样?似乎很奇怪......我唯一可以建议的另一件事是尝试导航属性,我相信它们的工作方式略有不同,但老实说我并不完全理解它们。或者,您可以使用 filter/where 子句从计划表中提取信息。然后运行一些连接语句来获得你需要的东西。代码不是很简洁,但应该可以加快速度。
    【解决方案3】:

    由于您正在执行预加载,因此如果您选择所需的实体,那么它就可以了。否则,您可以使用延迟加载,但正如您指定的那样,您不希望数据库往返,所以您可以避免它。

    我建议,如果多次使用此查询,那么您可以使用编译查询。从而提高性能。

    如果需要,请通过此链接.. http://msdn.microsoft.com/en-us/library/bb896297.aspx

    【讨论】:

      【解决方案4】:

      如果您使用DbContext,您可以在上下文中使用.Local 属性来查看您的实体是否已被检索并因此附加到上下文。

      如果查询之前已经运行,并且您的根 Plan 实体已经基于 Plan.Code == planId 附加,则可能它的子实体也已经附加,因为您进行了预加载,因此通过导航属性引用它们将不会t 在该上下文的生命周期内再次为他们访问数据库。

      article 可能有助于使用.Local

      【讨论】:

        【解决方案5】:

        也许可以通过使用投影而不是Include 来拉回您引用的实体,从而获得稍微更简洁的 SQL 查询:

        var planAggregate = 
         (from plan in entities.Plans
          let program = plan.Program
          let offers = program.Offers
          let fees = program.Fees
          //...
          where plan.Code == planCode
          select new {
            plan
            program,
            offers,
            fees,
            //...
          })
          .SingleOrDefault();
        

        如果您在上下文中禁用延迟加载,这种查询将导致您的实体的导航属性被包含在您的查询中的实体填充。

        (我只在 EF.dll v5.0 上对此进行了测试,但它在 EF.dll v4.4 上的行为应该相同,这只是 .NET 4.0 上的 EF5。当我使用此模式而不是 @ 进行测试时987654323@ 在类似形状的查询中,它从 500 行 SQL 中减少了大约 70 行。您的里程可能会有所不同。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多