1

私はlinqが初めてで、このクエリを書き始めました:

        var dProjects = Projects
         .Select(p => new Models.Project {
            ProjectID = p.ProjectID,
            Status = p.Status,
            ExpiresOn = p.ExpiresOn,
            LatestComments = p.ProjectComments
                               .OrderByDescending(pc => pc.CreatedOn)
                               .Select(pc => pc.Comments)
                               .FirstOrDefault(),                 
            ProjectFileIDs = p.ProjectFiles
                               .Select(pf => pf.BinaryFileID)
                               .AsQueryable()
         })
        .AsQueryable<Models.Project>();

関連するエンティティがネストされた選択を好み、作成するため、このクエリの実行が非常に遅いことは既にわかっていますが、機能し、必要な正しい結果が得られProjectCommentsます。ProjectFiles

このクエリを最適化して同じ結果を得るにはどうすればよいですか? 私の推測の 1 つは使用されますinner joinが、キーを介してデータベースProjectCommentsProjectFiles既に関係があるため、関係を再度設定することで何が達成できるかわかりません。

基本的に、パフォーマンスの観点から、ここで取るべき最善のアプローチを知る必要があります。注意すべきことの 1 つは、私は並べ替えProjectCommentsを行っており、最新のもののみを取得していることです。と の組み合わせを使用する必要がjoinありgroup by intoますか? 助けていただければ幸いです。ありがとう。

更新しました:

申し訳ありませんが、私がやろうとしていることについて十分に明確でなかったら. 基本的に、フロント エンドには、最新のプロジェクト コメントを含むプロジェクトのリストと、プロジェクトに関連付けられているすべてのファイルのリストを表示するグリッドがあり、ユーザーはそれらのリンクをクリックして実際にそれらのドキュメントを開くことができます。したがって、上記のクエリは機能しており、グリッドに次のように表示されます。

Project ID (プロジェクト テーブルから) Status (プロジェクト テーブルから) ExpiresOn (プロジェクト テーブルから) LatestComments (プロジェクト ID を外部キーとして持つ ProjectComments テーブルからの最新のエントリ) ProjectFileIDs (プロジェクト ID を外部キーとして持つ ProjectFiles テーブルからのファイル ID のリスト) - 私はそれらのファイル ID を使用し、ユーザーがそれらのファイルを開くことができるようにリンクを作成しています)。

すべてが機能しているので、すべてセットアップしましたが、クエリは少し遅くなります。現在、データはほとんどありません (テスト データのみ) が、これが開始されると、多くのユーザー/データが予想されるため、ライブになる前に、このクエリを最適化したいと考えています。したがって、ここでの目標は基本的に最適化することです。これはネストされた選択を作成するため、これが最善のアプローチではないと確信しています。

4

2 に答える 2

4

Entity Framework では、オブジェクトをプロジェクションではなくオブジェクト グラフとして返すことで、クエリのパフォーマンスを大幅に向上させることができます。Entity Framework は、最も複雑な SQL クエリを除くすべてを最適化するのに非常に効率的であり、遅延された「Eager」読み込みと「Lazy」読み込み (実際にアクセスされるまで関連項目を db から読み込まない) を利用できます。このMSDN リファレンスは、開始するのに適した場所です。

特定のクエリに関する限り、この手法を次のように使用できます。

var dbProjects = yourContext.Projects
                    .Include(p => p.ProjectComments
                              .OrderByDescending(pc => pc.CreatedOn)
                              .Select(pc => pc.Comments)
                              .FirstOrDefault()
                            )
                    .Include(p => p.ProjectFileIDs)
                    .AsQueryable<Models.Project>();

.Include()Eager Loading を意味するために使用されていることに注意してください。

関連オブジェクトのロードに関する MDSN リファレンスから、

パフォーマンスに関する考慮事項

関連するエンティティを読み込むパターンを選択するときは、データ ソースへの接続の数とタイミング、返されるデータの量、および 1 つのクエリを使用する複雑さに関して、各アプローチの動作を考慮してください。イーガー ロードでは、関連するすべてのエンティティが、クエリされたエンティティと共に 1 つのクエリで返されます。これは、データ ソースへの接続が 1 つしかない場合でも、最初のクエリで大量のデータが返されることを意味します。また、クエリ パスは、データ ソースに対して実行されるクエリで追加の結合が必要なため、より複雑なクエリになります。

明示的な遅延読み込みにより、関連するオブジェクト データが実際に必要になるまで、そのデータの要求を延期できます。これにより、より少ない合計データを返す、より単純な初期クエリが生成されます。ただし、関連するオブジェクトを連続して読み込むたびに、データ ソースへの接続が確立され、クエリが実行されます。遅延読み込みの場合、この接続は、ナビゲーション プロパティがアクセスされ、関連するエンティティがまだ読み込まれていないときに発生します。

于 2013-08-09T22:38:50.800 に答える