我在一个运行大约5000次的循环中有以下代码块。
IQueryable<IGrouping<int?, StatusLog>> allLogs = db.StatusLogs
.Where(sl => sl.ID.Value.Equals(foo))
.GroupBy(sl=>sl.bar);
List<StatusLog> statusLogs = new List<StatusLog>();
foreach (var group in allLogs)
{
// do stuff that adds to statusLogs
}
if (statusLogs.Count > 0)
{
// do stuff
}
我试图在代码中找到一个瓶颈,看似没有理由需要大约50毫秒。
即使allLogs
为空并且没有组,也需要50毫秒才能从
foreach (var group in allLogs)
到
if (statusLogs.Count > 0)
单步执行var group
和in allLogs
的评估只需要大约3毫秒,那么当foreach
循环内的代码没有进入下一个语句时,如何跳转到下一个语句需要50毫秒。甚至跑?
答案 0 :(得分:2)
将其溢出到db访问,然后将每个for循环和时间(使用StopWatch类)
var allLogs = db.StatusLogs
.Where(sl => sl.ID.Value.Equals(foo))
.GroupBy(sl=>sl.bar).ToList();// tolist forces query to run now
foreach (var group in allLogs)
{
// do stuff that adds to statusLogs
}
答案 1 :(得分:1)
那是因为allLogs
本质上是 lazy - 当foreach
中首次枚举时,它实际上会点击数据库(参见&#34;延迟查询执行&#34; here)。如果您像以下一样事先实现了集合,您将看到它快速逐步完成foreach
:
db.StatusLogs
.Where(sl => sl.ID.Value.Equals(foo))
.GroupBy(sl=>sl.bar)
.ToList(); // <-- pull the query results into memory