实体框架导航属性上的 .Skip().Take() 正在我的 SQL Server 上执行 SELECT *

发布于 2024-12-23 09:15:07 字数 930 浏览 4 评论 0原文

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

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

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

如果我删除 .ToList,该行速度很快(并且没有 SQL 发送到我的数据库),但是当我尝试对结果进行 foreach 时,我会得到发送到我的数据库的相同 SQL: 从子项中选择*.*

在实体的导航属性上使用 .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 并将它们也呈现出来。

I have a method on my generated partial class like this:

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

When I look at my SQL Server, I can see the generated code is doing a SELECT *.* FROM Children This code is taken directly from my class, I have verified that the order of my Skip/Take is BEFORE my .ToList.

If I remove the .ToList, that line is fast (and no SQL is sent to my DB), but the moment I try to foreach over the results, I get the same SQL sent to my DB: SELECT *.* FROM Children.

Is there something special I need to do when using .Skip and .Take on the navigation properties of my entities?

update

I'll try to get the actual SQL generated, I'm not currently setup for that. I found the first one because it shows up in SSMS's "recenty expensive queries" list.

Running this:

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

returns ~4,000,000 rows and takes ~25 seconds.

Running this:

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

returns ~4,000,000 rows and takes ~25 seconds.

As I said, I'll grab the SQL generated for these and pose them up as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情愿 2024-12-30 09:15:07

问题在于,当您查询这样的子集合时,您正在执行 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();

The problem is that you are performing a LINQ-to-Object query when you query a child collection like that. EF will load the whole collection and perform the query in memory.

If you are using EF 4 you can query like this

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

In EF 4.1

var pChildren = context.Entry(this)
                   .Collection(e => e.Children)
                   .Query()
                   .OrderBy(/* */).Skip(skipRelated).Take(takeRelated)
                   .Load();
那小子欠揍 2024-12-30 09:15:07

如果您对 Take 的结果调用 Skip 有帮助吗?即

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

另请参阅

Does it help if you call Skip on the result of Take? i.e.

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

Also, see

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文