简体   繁体   中英

Filter included property using EF Core?

I am currently creating a beer website and I want to filter beers by style using a simple query like so:

IQueryable<Beer> result = this.context.Beers
                                      .Include(b => b.Brewery)
                                      .Include(b => b.Style)
                                      .Include(b => b.Reviews)
                                      .ThenInclude(r => r.User)
                                      .Where(b => b.IsDeleted == false);

if (searchCriteria != null)
{
    if (type == "Name")
    {
        result = result.Where(b => b.Name.Contains(searchCriteria));
    }
    else if (type == "Style")
    {
        result = result.Where(b => b.Style.Name.Contains(searchCriteria));
    }
    else
    {
        result = result.Where(b => b.Brewery.Name.Contains(searchCriteria));
    }
}

However when it is executed I get 0 results since the query hasn't been materialized and the Style property are null, even though they have been included.

How can I get around this issue?

To materialize the query, just add .ToList() .

So, at the end of the snippet, you can use

result.ToList()

Be careful though, some of the conditions in your Where clauses can lead to potential performance problems. Don't forget to create indexes, especially if your db starts to be big.

Note that you should not materialize using ToList() too early (before the search criterias) either, because that would mean taking all the table in memory before filtering.

I haven't tried it but it should be possible to generate your query first before finally materializing your query with the eager loading. That way you get the database to do the heavy lifting rather than.Net.

IQueryable<Beer> result = this.context.Beers.Where(b => b.IsDeleted == false);

if (searchCriteria != null)
{
    if (type == "Name")
    {
        result = result.Where(b => b.Name.Contains(searchCriteria));
    }
    else if (type == "Style")
    {
        result = result.Where(b => b.Style.Name.Contains(searchCriteria));
    }
    else
    {
        result = result.Where(b => b.Brewery.Name.Contains(searchCriteria));
    }
}

List<Beer> materialisedResults = result
                                   .Include(b => b.Brewery)
                                   .Include(b => b.Style)
                                   .Include(b => b.Reviews)
                                   .ThenInclude(r => r.User).ToList();

First, check if all data has been coming on the result or not, then.ToList() will execute to store all of the data in the result, then you can query.

var result = this.context.Beers
                         .Include(b => b.Brewery)
                         .Include(b => b.Style)
                         .Include(b => b.Reviews)
                         .ThenInclude(r => r.User)
                         .Where(b => b.IsDeleted == false).ToList();

            if (searchCriteria != null)
            {
                if (type == "Name")
                {
                    result = result.Where(b => b.Name.Contains(searchCriteria));
                }
                else if (type == "Style")
                {
                    result = result.Where(b => b.Style.Name.Contains(searchCriteria));
                }
                else
                {
                    result = resultWhere(b => b.Brewery.Name.Contains(searchCriteria));
                }
            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM