EF 4.1 / SQL Server 2008的命令超时

时间:2011-11-17 23:48:16

标签: entity-framework

我看到多次询问如何使用Entity Framework为长时间运行的查询设置命令超时的问题。我现在遇到的问题是,针对服务器运行的查询实际上并不需要那么长的时间来执行和返回。

以下是运行查询的代码:

var records = (from c in _context.Set<CompletedQuiz>()
              where c.FarmId == _entityId && c.ToolboxId == _toolboxId
              group c by new { c.UserId, c.LessonId } into g
              select g).ToList()
              .Select(c => new {
                              UserId = c.Key.UserId,
                              LessonId = c.Key.LessonId,
                              NumQuestions = c.Max(n => n.TotalNumQuestions),
                              NumLessons = c.Select(l => l.LessonId).Distinct().Count(),
                              Start = c.Min(s => s.LogonDateTime),
                              End = c.Max(e => e.LogoffDateTime),
                              MaxScore = c.Max(s => s.Score),
                              Passed = c.Any(p => p.Passed)
                          });

我从一个名为CompletedQuizzes的相当简单的视图中进行选择,并为用户和课程分组记录ID。我运行SQL Profiler运行它来捕获已执行的实际查询;如果我在SSMS中运行完全相同的查询,它几乎立即运行(<0秒)。但是,从我的应用程序运行通常会超过30秒的默认命令超时。我在上面显示的行上放了一个断点,然后我将调用添加到.ToList()以确保查询立即执行。

我还应该检查另外一个可能的罪魁祸首?

编辑:
我仍然不明白为什么上面的代码执行时间太长,但我使用Linq扩展方法重新编写它,现在它运行速度和我预期的一样快。这就是现在的样子:

var records = _context.Set<CompletedQuiz>()
                      .Where(c => c.FarmId == _entityId && c.ToolboxId == _toolboxId)
                      .GroupBy(c => new { c.UserId, c.LessonId })
                      .Select(c => new {
                                      UserId = c.Key.UserId,
                                      LessonId = c.Key.LessonId,
                                      NumQuestions = c.Max(n => n.TotalNumQuestions),
                                      NumLessons = c.Select(l => l.LessonId).Distinct().Count(),
                                      Start = c.Min(s => s.LogonDateTime),
                                      End = c.Max(e => e.LogoffDateTime),
                                      MaxScore = c.Max(s => s.Score),
                                      Passed = c.Any(p => p.Passed)
                                  });

我想在这一点上我会调整我的问题为什么第二个代码块生成的查询从我的应用程序执行得更快?

1 个答案:

答案 0 :(得分:1)

我认为您的第一个查询显然是使用.ToList()进行投影。这意味着您将满足条件的所有CompleteQuiz实例加载到您的应用程序并执行应用程序中的所有聚合。这也意味着必须有很多后续查询来延迟加载聚合计算的关系。

在第二个查询中没有ToList,因此在数据库中执行包括所有聚合的整个查询。