【问题标题】:c# foreach loop iterations with list from query execution timec# foreach 循环迭代与查询执行时间的列表
【发布时间】:2020-11-07 09:53:12
【问题描述】:

这只是我需要的信息。

当我使用 C# 遍历列表执行 foreach 循环时,如下所示:

foreach (var record in DbContext.UserRecords.Where(record => record.UserId == user.Id &&
                                                                record.Date.Date == startDate.AddDays(i).Date)
                                                                .ToList())
{
    totHours += record.Hours;
}

每个周期到底发生了什么?查询是否再次发生,所以我对我想要的列表中的每个项目都有 N 次查询,或者它只是第一次执行,然后循环保留数据的临时副本? 我正在尝试优化 ASP.Net 项目中的时间,我想知道是否有更清洁/更快的方法来迭代这些长数据流...

非常感谢!

【问题讨论】:

  • 如果你想优化一个项目,你应该通过分析器运行它而不是猜测!
  • 另外,如果您只是对小时求和,您可以让查询只返回小时的总和。 totHours += DbContext.UserRecords.Where(/* conditions */).Sum(record => record.Hours);
  • @itsme86 我喜欢这种超级精简的方法!谢谢你的主意!

标签: c# sql sqlite foreach asp.net-core-3.1


【解决方案1】:

不,您在 IQueryable 上调用 ToList(),它会执行查询并将数据加载到内存中。

然后对内存中的对象执行每次迭代。

即使没有ToList(),查询也会执行一次,并且数据会从数据库中流出。

虽然内存效率更高,但它会在循环期间锁定基础表,因此您需要谨慎使用这种方法。

【讨论】:

  • 我也想了解一下lil。虽然我知道 EF。但特别是在这个循环中。因为.ToList() 被调用。不会每次迭代都会被一次又一次地调用吗?
  • 根据你在开始时所说的只有一次实际查询将被执行到数据库,然后在每次迭代时内存中获取的记录将用于执行迭代?
  • @RaoHammas 不,in 之后的表达式被评估为 IEnumerable。对于ToList(),这是一个List<T>,它是一个内存对象。如果没有ToList()IEnumerable 将导致数据在每次迭代时都被流式传输。
  • @JohnathanBarclay 谢谢先生,这只是我需要的确认,我认为它正在按照您描述的方式进行操作,但我只是想确保......有时我确实犯了非常可怕的错误,检查两次是绝不是一个坏主意 XD
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-29
  • 2018-11-18
  • 2012-09-02
  • 1970-01-01
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多