【问题标题】:.Skip().Take() on Entity Framework Navigation Properties is executing SELECT * on my SQL Server实体框架导航属性上的 .Skip().Take() 正在我的 SQL Server 上执行 SELECT *
【发布时间】:2011-12-28 23:17:04
【问题描述】:

我在生成的部分类上有一个方法,如下所示:

var pChildren = this.Children
    .Skip(skipRelated)
    .Take(takeRelated)
    .ToList();

当我查看我的 SQL Server 时,我可以看到生成的代码正在执行 SELECT *.* FROM Children 此代码直接取自我的课程,我已验证我的 Skip/Take 顺序在我的 .ToList 之前。

如果我删除 .ToList,该行很快(并且没有 SQL 发送到我的数据库),但是当我尝试 foreach 超过结果时,我收到相同的 SQL 发送到我的数据库:@987654324 @。

在我的实体的导航属性上使用 .Skip 和 .Take 时,我需要做些什么特别的事情吗?

更新

我将尝试生成实际的 SQL,我目前还没有为此设置。我找到了第一个,因为它出现在 SSMS 的“最近昂贵的查询”列表中。

运行这个:

var pChildren = this.Children
    //.Skip(skipRelated)
    //.Take(takeRelated)
    .ToList();

返回约 4,000,000 行,耗时约 25 秒。

运行这个:

var pChildren = this.Children
    //.Skip(skipRelated)
    .Take(takeRelated)
    .ToList();

返回约 4,000,000 行,耗时约 25 秒。

正如我所说,我将获取为这些生成的 SQL 并将它们也摆出来。

【问题讨论】:

  • 您希望这段代码生成什么 SQL?
  • 我希望有类似 SELECT TOP 10 FROM Children WHERE ParentID = @idOfParentEntity 的东西(我忘记了 EF 是如何处理 .Skip 的,但我已经读过它应该这样做了。如果我直接针对我的上下文执行此查询,它似乎会限制返回到特定“页面”的数据)
  • 在没有 Skip/Take 的情况下执行此查询并再次在没有 Take 的情况下执行此查询并发布为每个查询生成的 SQL 可能很有用。其中之一可能是问题所在。
  • @cdhowie - 例如,您可以在 SQL Server 中使用 ROW_NUMBER 返回 10-20 之间的行。
  • 能否显示通过以下命令执行的实际查询((ObjectQuery<Child>)this.Children.Skip(skipRelated).Take(takeRelated)).ToTraceString()

标签: c# .net entity-framework sql-server-2008-r2 navigation-properties


【解决方案1】:

问题是当您查询这样的子集合时,您正在执行 LINQ-to-Object 查询。 EF 将加载整个集合并在内存中执行查询。

如果你使用的是 EF 4,你可以这样查询

var pChildren = this.Children.CreateSourceQuery()
                 .OrderBy(/* */).Skip(skipRelated).Take(takeRelated);

在 EF 4.1 中

var pChildren = context.Entry(this)
                   .Collection(e => e.Children)
                   .Query()
                   .OrderBy(/* */).Skip(skipRelated).Take(takeRelated)
                   .Load();

【讨论】:

  • 正是我需要的。我使用的是 EF4.1,但第一个查询对我来说效果更好,因为我无法通过这个特定方法访问我的上下文。
【解决方案2】:

如果您根据Take 的结果调用Skip 会有帮助吗?即

table.Take(takeCount+skipCount).Skip(skipCount).ToList()

另见

【讨论】:

  • 在跳过之前拍摄没有意义
  • @vittore:当然可以。如果你想要记录 51-100,而不是拿一百万给客户,扔掉 50,保留 50,然后扔掉剩下的,你可以拿 100 给客户,扔掉 50。
  • @BenVoigt 虽然这是真的,但它并没有像你到达最后一页那样有帮助。
猜你喜欢
  • 2016-05-01
  • 2021-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多