3

私は、Entity Framework Profiler を使用した後に非常にばかげているように見えるデザイン パターンを使用してきました。

エンティティ クラスを拡張して、そのエンティティに関連付けられたコレクションのフィルター処理されたビューであるプロパティを持たせました。このような:

public IEnumerable<Member> ActiveMembers
{
    get
    {
        return Members.Where(t => t.LeftDate == null);
    }
}

私は主にクラブを離れていないメンバーに関心があるので、このプロパティは非常に便利で、理にかなっているように思えました。

しかし、EF Profiler を実行した結果、これが N+1 の問題を引き起こすことが多いことがわかりました。メンバーをループし、そのアドレスも表示したい場合、アドレスに対する各リクエストは余分な db クエリになります。

この質問から、自分のプロパティを次のように変更できることを知りました。

return Members.CreateSourceQuery().Include("Address")
              .Where(t => t.LeftClubDate == null);

これにより、この場合の N+1 問題は解消されますが、アドレス情報が常に必要なわけではなく、Member から別のナビゲーション プロパティをたどりたい場合があります。

理想的には、ActiveMembers などのフィルタリングされたプロパティの柔軟性を維持し、クエリに含めるプロパティを後で決定できるようにしたいと考えています。このような:

var membersToDisplay = ActiveMembers.Include("Address").ToList();

これは可能ですか、またはフィルタリングされたプロパティのアイデアを再構築する必要がありますか?

4

1 に答える 1

3

いいえ、電話をかけることはできませIncludeIEnumerableIncludeObjectQuery/の特徴ですDbQuery。(EFv4.1 またはカスタム拡張を使用して) 呼び出すことは可能ですが、渡されたクエリを or に内部的にキャストし、キャストを実行Includeできない場合は例外をスローします。アプリケーションを再設計する必要があります。IQueryableObjectQueryDbQuery

必ずしも住所情報が必要なわけではなく、Member から別のナビゲーション プロパティをたどりたい場合があります。

現在のニーズに基づいてデータを入力するか、N + 1 問題に対処する必要があります。たとえば、別の linq クエリを使用できます。

var clubId = ActiveClub.Id;
var members = (from member in context.Members.Include("Address")
               where member.LeftDate == null and member.ClubId == clubId
               select member).ToList();
于 2011-05-14T13:02:07.800 に答える