8

生成された部分クラスに次のようなメソッドがあります。

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

SQL Serverを見ると、生成されたコードが実行していることがわかります。SELECT *.* FROM Childrenこのコードはクラスから直接取得され、Skip/Takeの順序が.ToListの前であることを確認しました。

.ToListを削除すると、その行は高速になります(そして、SQLはDBに送信されません)がforeach、結果を確認しようとすると、同じSQLがDBに送信されますSELECT *.* FROM Children

.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をつかみ、それらも提起します。

4

2 に答える 2

7

問題は、そのような子コレクションをクエリするときにLINQ-to-Objectクエリを実行していることです。EFはコレクション全体をロードし、メモリ内でクエリを実行します。

EF 4を使用している場合は、次のようにクエリできます

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

EF4.1では

var pChildren = context.Entry(this)
                   .Collection(e => e.Children)
                   .Query()
                   .OrderBy(/* */).Skip(skipRelated).Take(takeRelated)
                   .Load();
于 2011-12-29T00:04:12.547 に答える
1

Skipあなたがの結果を求めるならば、それは助けになりますTakeか?すなわち

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

また、参照してください

于 2011-12-28T23:36:27.427 に答える