15

Linq を使用して、ナビゲーション プロパティを関連エンティティのサブセットにフィルター処理する方法を見つけたいと思います。この件に関するすべての回答は、次のような匿名セレクターを実行することを提案していることを知っています。

query.Where(x => x.Users.Any(y => y.ID == actingUser.ID))
    .Select(x => new
    {
        Event = x,
        Discussions = x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())
    })
    .OrderBy(x => x.Discussions.Count())
    .ThenBy(x => x.Event.Name);

ただし、クエリ生成の一般的な性質により、これは理想的とは言えません。また、プロファイラーをスローすると、非常に恐ろしい SQL クエリが生成されます。

私は次のようなことを達成できるようにしたいと思います:

query.Include(x => x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>()))
        .OrderBy(x => x.Discussions.Count())
        .ThenBy(x => x.Name);

これは EF5 (またはその点についてはどのバージョンでも) でサポートされていないことを認識していますが、匿名型の select ステートメントを掘り下げることなく、Linq を介して結果セットを制約する方法が必要です。

私は次のようなことを試みました:

query.GroupJoin(discquqery, 
    x => x.ID,
    x => x.Event.ID, 
    (evt, disc) => evt.Discussions = disc.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())).ToList();

ただし、ラムダ式内で割り当てを行うことはできず、ここで匿名型を選択すると、選択を使用した場合と同じジレンマが発生します。

EFが生成する方法(私が見つけることができる)を提供しない理由を理解できないと思います:

SELECT
    --Properties
FROM Event e
LEFT OUTER JOIN Discussions d
    ON e.ID = d.EventID AND --Additional constraints
WHERE
    --Where conditions
ORDER BY
    --Order Conditions

SQL で結合を制約するのは非常に簡単で、Linq を介してそれを行う方法も必要です。

PS: スタック、MSDN、experts-exchange などを検索しました。これは重複していないことを認識してください。この主題に触れても、「それはできません」という答えが出るか、まったく答えられません。不可能なことはありません... これも含めて。

4

1 に答える 1

8

この主題に触れても、「それはできません」という答えが出るか、まったく答えられません。不可能なことはありません... これも含めて。

もちろん。可能です。EF ソース コードをダウンロードして、この機能を自分で追加できます。オープン ソース プロジェクトとコミュニティに大きく貢献します。EFチームはあなたの努力を喜んでお手伝いします.

現在のバージョンでは「できない」というのが答えです。質問の冒頭で説明したように、匿名型または特別なマップされていない型への射影を使用できます。その他のオプションは、単一の親の関連エンティティをロードする個別の明示的なクエリ、またはすべての親の関連エンティティをロードする個別のクエリです。

単一の親のリレーションをロード:

context.Entry(event)
       .Collection(e => e.Discussions)
       .Query()
       .Where(d => ...)
       .Load();

すべての親のリレーションを読み込みます (遅延読み込みをオフにする必要があります):

// load all parents
var events = query.Where(e => ...).ToList();

// load child filtered by same condition for parents and new condition for children
childQuery.Where(d => e.Event ... && d.Something ...).Load();

2 番目の解決策では、子が親に戻るナビゲーション プロパティを持つ必要があります (最初に親を読み込むために使用されたのと同じクエリ条件を構築するため)。すべてが正しく構成され、エンティティがアタッチされている場合、EF は親エンティティの関係 (コレクション) を自動的に修正する必要があります (ただし、動的プロキシのコレクションが読み込まれたとマークされないため、これを遅延読み込みと一緒に使用できないのはそのためです)。

于 2013-02-07T09:09:20.240 に答える