Linq请求向DB提出了很多疑问

Ark*_*hel 5 c# entity-framework-core

我有这样的ef类:

class Product 
{
  public int ProductId {set; get;}
...
 public List<ProductBannedIn> BannedIn;
}

public class ProductBannedIn
{
  public int ProductId {set; get;}
  public Product Product {set; get;}
  public int CountryId {set; get;}
  public Country Country {set; get;}
}
Run Code Online (Sandbox Code Playgroud)

并希望提出如下要求:

... //query - added some filters before
var products = query.Include(x => x.BannedIn)
    .Join(context.ProductTranslation
        .Where(x => x.LanguageId == language.LanguageId),
           product => product.ProductId,
              translation => translation.Product.ProductId,
                  (x,y) => new {
                      Id = x. ProductId,
                      Name = y.Name,
                      Description = y.Description,
                      Type = x.TypeId,
                      BannedIn = x.BannedIn.Select(b => b.CountryId),
                   }).ToList();
Run Code Online (Sandbox Code Playgroud)

问题:问题是,当我拿到1000个产品这部分时

BannedIn = x.BannedIn.Select(b => b.CountryId)
Run Code Online (Sandbox Code Playgroud)

对每一行进行查询,并且非常慢.我在调试器中看到的每个产品都会使查询获取BannedIn,但是应该已经获取因为我已经包含

需要实现的目标:
一般应该像对数据库的1个查询而不是每行(x.BannedIn)

Iva*_*oev 5

这是一个已知的(所谓的N + 1查询)问题,在2.1 EF EF版本中具有相关子查询.它已在2.1中修复 - 请参阅EF Core 2.1中的新功能 - 相关子查询的优化:

我们改进了查询转换,以避免在许多常见场景中执行"N + 1"SQL查询,其中投影中导航属性的使用导致将来自根查询的数据与来自相关子查询的数据相关联.优化需要缓冲子查询的结果,并且我们要求您修改查询以选择新的行为.

因此,如果可能,请升级到最新的EF Core位,然后通过添加.ToList()到相关子查询来"选择加入"优化,如文档链接中所述:

BannedIn = x.BannedIn.Select(b => b.CountryId).ToList(),
Run Code Online (Sandbox Code Playgroud)

结果将是执行2个SQL查询(这是EF Core与相关集合一起工作的方式 - 每个集合1个SQL查询),但当前每个产品不是1个.