web-dev-qa-db-ja.com

ネストされたコレクションのEntity Frameworkオブジェクトをフィルタリングする方法は?

問題は次のとおりです。フィルター処理されたネストされたコレクションを持つオブジェクトのコレクションを返す必要があります。例:注文のあるストアがあり、注文のネストされたコレクションを含むが、削除済みとしてマークされた顧客からの注文のないストアのコレクションを返す必要があります。

これが私がやろうとしていることです。しかし、まだ運はありません。提案は大歓迎です:)

public List<StoreEntity> GetStores(Func<Store, bool> storeFilter, Predicate<OrderEntity> orderFileter)
{
    IQueryable<StoreEntity> storeEntities = Context.Stores
        .Include(o => o.Order)
        .Include(cu => cu.Orders.Select(c => c.Customer))
        .Where(storeFilter)
        //.Where(rcu=>rcu.Orders.Select(cu=>cu.Customer.Deleted==false)) //just test this doesn't work
        .AsQueryable();

    List<StoreEntity> storeEntities = storeEntities.ToList();

    //storeEntities.ForEach(s => s.Orders.ToList().RemoveAll(c=>c.Customer.Deleted==true)); // doesn't work

    foreach (StoreEntity storeEntity in storeEntities)
    {
        storeEntity.Orders.ToList().RemoveAll(r=>r.Customer.Deleted==true);
    }

    return storeEntities;
}

問題は、フィルターが適用されないことです。 trueとして設定されたフラグを削除した顧客は、コレクションに残ります。

22
Nazar Gargol

それを「きちんとした」方法で直接行うことはできませんが、いくつかのオプションがあります。
まず、ストアを取得した後、子コレクションを明示的にロードできます。 関連するエンティティを明示的に読み込むときにフィルターを適用する セクションを参照してください。

データベースに余分にアクセスしたくない場合は、独自のクエリを作成し、親コレクションとフィルター処理された子コレクションを別のオブジェクトに手動で投影する必要があります。例については、次の質問を参照してください。
Linq To Entities-子エンティティでフィルタリングする方法
LINQクエリ-積極的なフェッチでの並べ替えとフィルタリングの方法

編集

ちなみに、最初の.Where(rcu=>rcu.Orders.Select(cu=>cu.Customer.Deleted==false))の試行は機能しません。この方法では、ネストされたコレクション(たとえば、顧客を削除していないすべてのストア)ではなく、親コレクション(ストア)にフィルターを適用するため)。
論理的には、ネストされたコレクションをフィルタリングするコードは、Includeメソッドに配置する必要があります。現在、IncludeSelectステートメントのみをサポートしていますが、個人的には、EFチームが次のようなものを実装するときだと思います。

.Include(cu => cu.Orders.Select(c => c.Customers.Where(cust => !cust.IsDeleted)));
31
Yakimych

現在お持ちのコードの問題は次の行です:

_storeEntity.Orders.ToList().RemoveAll(r=>r.Customer.Deleted==true);
_

storeEntity.Orders.ToList()は、_List<OrderEntity>_の内容を持つnew _storeEntity.Orders_を返します。この新しいリストから、削除されたすべての顧客を削除します。ただし、このリストはその後使用されません。

ただし、たとえあなたがしたいことをしたとしても、StoreEntityオブジェクトはまだデータコンテキストに接続されているため、データベースからそれらの顧客も削除されます。

コメント付きのWhereで最初に試したように、本当にフィルターを使用したいでしょう。ヤキミーチの回答を参照してください。

3
Daniel Hilgarth