Тайм-аут команды с EF 4.1 / SQL Server 2008 - PullRequest
1 голос
/ 18 ноября 2011

Я вижу, что несколько раз задавался вопрос о том, как установить время ожидания команды для длительных запросов с 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 и группирую идентификаторы записей для пользователей и уроков.Я запустил это с запущенным SQL Profiler для захвата фактического выполненного запроса;если я выполняю тот же самый запрос в SSMS, он выполняется почти мгновенно (<0 секунд).Тем не менее, запуск из моего приложения часто превышает время ожидания команды по умолчанию 30 секунд.Я поставил точку останова на строке, показанной выше, и добавил вызов к <code>.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 Ответ

1 голос
/ 18 ноября 2011

Я думаю, совершенно очевидно, что ваш первый запрос использует .ToList() перед проекцией. Это означает, что вы загружаете все CompleteQuiz экземпляры, удовлетворяющие вашему условию, в ваше приложение и выполняете все агрегации в вашем приложении. Это также означает, что должно быть много последующих запросов, чтобы лениво загрузить ваши отношения для вычислений агрегации.

В вашем втором запросе нет списка ToList, поэтому весь запрос, включая все агрегаты, выполняется в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...