繁体   English   中英

如何在Linq中避免“选择n + 1”模式

[英]How to avoid “select n+1” pattern in Linq

我有以下形式的查询(包括LinqKit):

Expression<Func<Country, DateTime, bool>> countryIndepBeforeExpr = 
  (ct, dt) => ct.IndependenceDate <= dt;
DateTime someDate = GetSomeDate();
var q = db.Continent.AsExpandable().Select(c =>
  new 
  {
    c.ID,
    c.Name,
    c.Area,
    Countries = c.Countries.AsQueryable()
                 .Where(ct => countryIndepBeforeExpr.Invoke(ct, someDate))
                 .Select(ct => new {ct.ID, ct.Name, ct.IndependenceDate})
  });

现在我想通过迭代q ...但由于Countries的每个元素的属性的类型的IQueryable ,这将是懒加载,导致被执行N + 1个查询,这是不是很好。

编写此查询以便所有必要的数据将在单个查询中提取到db的正确方法是什么?

编辑

嗯,如果我在问这个问题之前实际运行了Sql跟踪,那可能会有所帮助。 以为 ,因为内财产是类型的IQueryable ,这将是懒加载...但是做了一些实际测试后,事实证明,LINQ到实体是足够聪明的同时运行整个查询。

很抱歉浪费您的全部时间。 我将删除该问题,但是由于它已经有了答案,所以不能。 也许可以作为对他人的某种警告,在假设它成立之前对您的假设进行检验

呼叫大洲时,将国家/地区包括在模型中。 用这样的东西:

var continents = db.Continent.Include(c => c.Countries).ToArray();

然后,您可以在没有iQueryable对象的情况下进行linq操作。

认为这应该工作(将AsExpandable()移到IQueryable根目录):

var q = db.Continent
          .AsExpandable()
          .Select(c => new 
          {
              c.ID,
              c.Name,
              c.Area,
              Countries = c.Countries
                  .Where(ct => countryIndepBeforeExpr.Invoke(ct, someDate))
                  .Select(ct => new {ct.ID, ct.Name, ct.IndependenceDate})
});

如果没有,请创建两个IQueryable并将它们连接在一起:

var continents = db.Continents;
var countries = db.Countries
                  .AsExpandable()
                  .Where(c => countryIndepBeforeExpr.Invoke(c, someDate))
                  .Select(c => new { c.ID, c.Name, c.IndependenceDate });

var q = continents.GroupJoin(countries,
    continent => continent.ID,
    country => country.ContinentId,
    (continent, countries) => new
    {
        continent.ID,
        continent.Name,
        continent.Area,
        Countries = countries.Select(c => new
        {
            c.ID,
            c.Name,
            c.IndependenceDate
        })
    });

暂无
暂无

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

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