0

我有一个形式的查询(包括 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每个元素的属性都是 type IQueryable,它将被延迟加载,导致执行 n+1 个查询,这不是很好。

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

编辑

嗯,如果我在问这个问题之前实际运行了 Sql 跟踪,那可能会有所帮助。我假设因为内部属性的类型IQueryable是延迟加载的……但是在进行了一些实际测试之后,事实证明 Linq to Entities 足够聪明,可以一次运行整个查询。

很抱歉浪费了你所有的时间。我会删除这个问题,但因为它已经有了答案,所以我不能。也许它可以作为对其他人的某种警告,在假设它是真的之前测试你的假设!

4

2 回答 2

1

当您调用大陆时,将国家/地区包括到您的模型中。像这样:

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

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

于 2014-03-04T14:42:56.473 回答
0

认为这应该有效(移动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
        })
    });
于 2014-03-04T15:07:00.123 回答