简体   繁体   English

使用 EF Core 过滤包含的属性?

[英]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.但是,当它执行时,我得到 0 结果,因为查询尚未实现并且 Style 属性是 null,即使它们已被包含在内。

How can I get around this issue?我该如何解决这个问题?

To materialize the query, just add .ToList() .要实现查询,只需添加.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.不过要小心, Where子句中的某些条件可能会导致潜在的性能问题。 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.请注意,您也不应该过早地使用ToList() (在搜索条件之前),因为这意味着在过滤之前获取 memory 中的所有表。

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.这样,您就可以让数据库而不是.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.首先,检查结果中是否有所有数据,然后执行.ToList() 将结果中的所有数据存储,然后您可以查询。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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