Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.1k views
in Technique[技术] by (71.8m points)

linq - How to filter nested collection Entity Framework objects?

Here is the problem: I need to return a collection of objects with filtered nested collections. E.g: there is a store with orders and I need to return a collection with stores that includes nested collections with orders but without orders from customers that are marked as deleted.

Here is what I try to do. But still no luck. Any suggestions are appreciated :)

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;
}

The problem is that the filter is not applied. Customers that have deleted flag set as true stay in the collection.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can't do that directly in a "neat" way, but you have a few options.
First of all, you can explicitly load the child collection after you've fetched the stores. See the Applying filters when explicitly loading related entities section.

If you don't want to make extra trips to the database, you will have to construct your own query and project the parent collection and the filtered child collections onto another object manually. See the following questions for examples:
Linq To Entities - how to filter on child entities
LINQ Query - how sort and filter on eager fetch

Edit

By the way, your first .Where(rcu=>rcu.Orders.Select(cu=>cu.Customer.Deleted==false)) attempt doesn't work since this way you are applying a filter to your parent collection (stores) rather than the nested collection (e.g. all the stores that don't have deleted customers).
Logically, the code filtering the nested collection should be placed in the Include method. Currently, Include only supports a Select statement, but personally I think it's time for the EF team to implement something like:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...