Мне очень нужна помощь с этим и не удалось найти соответствующие ответы после нескольких часов поиска.Entity Framework 6 - Группировка по заказу First() занимает слишком много времени
MySQL, Entity Framework 6, база данных с несколькими миллионами записей, запись выглядит следующим образом:
Indexint (11) NOT NULL
TaskIDint (11) NOT NULL
DeviceIDbigint (20) NOT NULL
Commentslongtext NULL
ExtendedResultslongtext NULL
RunResultint (11) NOT NULL
JobResultint (11) NOT NULL
JobResultValuedouble NOT NULL
ReporterIDbigint (20) NOT NULL
FieldIDbigint (20) NOT NULL
TimeOfRundatetime NOT NULL
Что мне нужно, чтобы получить все записи для конкретного TaskId, затем группу по DeviceID и сортировать по TimeOfRun для того, чтобы получить последние данные для каждого идентификатора устройства в конкретном идентификаторе задачи.
Это мой код:
List<JobsRecordHistory> newH = db.JobsRecordHistories.AsNoTracking().Where(x => x.TaskID == taskID).GroupBy(x => x.DeviceID).
Select(x => x.OrderByDescending(y => y.TimeOfRun).FirstOrDefault()).ToList();
Но это генерируется запрос:
{SELECT
Apply1
. Index
, Apply1
. TaskID
, Apply1
. DEVICEID1
AS DeviceID
, Apply1
. RunResult
, Apply1
. JobResult
, Apply1
. JobResultValue
, Apply1
. ExtendedResults
, Apply1
. Comments
, Apply1
. ReporterID
, Apply1
. FieldID
, Apply1
. TimeOfRun
ОТ (SELECT Project2
. p__linq__0
, Project2
. DeviceID
, (SELECT Project3
. Index
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
DESC LIMIT 1) AS Index
, (SELECT Project3
. TaskID
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
.TimeOfRun
DESC LIMIT 1) TaskID
, (SELECT Project3
. DeviceID
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
по убыванию ПРЕДЕЛ 1) КАК DEVICEID1
, (SELECT Project3
. RunResult
ОТ JobsRecordHistories
КАК ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
DESC LIMIT 1) А.С. RunResult
, (SELECT Project3
. JobResult
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
по убыванию ПРЕДЕЛ 1) КАК JobResult
, (SELECT Project3
. JobResultValue
ОТ JobsRecordHistories
КАК Project3
WHERE (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
DESC LIMIT 1) А.С. JobResultValue
, (SELECT Project3
. ExtendedResults
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
по убыванию ПРЕДЕЛ 1) КАК ExtendedResults
, (SELECT Project3
. Comments
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
DESC LIMIT 1) А.С. Comments
, (SELECT Project3
. ReporterID
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
по убыванию ПРЕДЕЛ 1) AS ReporterID
, (SELECT Project3
.FieldID
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
DESC LIMIT 1) А.С. FieldID
, (SELECT Project3
. TimeOfRun
ОТ JobsRecordHistories
КАК Project3
ГДЕ (Project3
. TaskID
= @ p__linq__0) И (Project2
. DeviceID
= Project3
. DeviceID
) ORDER BY Project3
. TimeOfRun
по убыванию ПРЕДЕЛ 1) КАК TimeOfRun
ОТ (SELECT @ p__linq__0 А.С. p__linq__0
, Distinct1
. DeviceID
FROM (SELECT DISTINCT Extent1
. DeviceID
ОТ JobsRecordHistories
AS Extent1
ГДЕ Extent1
. TaskID
= @ p__linq__0) AS Distinct1
) AS Project2
) AS Apply1
}
Который занимает слишком много времени.
Я не знаю SQL достаточно хорошо, признаю, но если вставить инструкцию ToList() после инструкции WHERE, то я получаю результаты гораздо быстрее, хотя это все еще не так, потому что есть много не- необходимые данные, которые база данных переходит к моему приложению в этой ситуации, и она по-прежнему медленная = 30 секунд для 40 тыс. записей.
Я также попытался это:
Dictionary<long, DateTime> DeviceIDAndTime = db.JobsRecordHistories.AsNoTracking().Where(x => x.TaskID == taskID).GroupBy(x => x.DeviceID)
.Select(g => new DeviceIDaAndTime { deviceID = g.Key, timeOfRun = g.Max(gi => gi.TimeOfRun) }).ToDictionary(x => x.deviceID, x => x.timeOfRun);
Для того, чтобы использовать словарь таким образом:
List<JobsRecordHistory> newH = db.JobsRecordHistories.AsNoTracking().Where(x => DeviceIDAndTime.Keys.Contains(x.DeviceID) && x.TimeOfRun == DeviceIDAndTime[x.DeviceID]).ToList();
Но я получаю эту ошибку:
Additional information: LINQ to Entities does not recognize the method 'System.DateTime get_Item(Int64)' method, and this method cannot be translated into a store expression.
который имеет смысл причину от что я понимаю, при сравнении значения timeOfRun со значением словаря LINQ требуется определенное значение, а не коллекция, когда составление запроса.
Странно, что я не нашел никакого связанного сообщения и что другие люди не столкнулись с этой проблемой. Наверное, я что-то пропустил.
Цените любую помощь, спасибо
Вы можете использовать хранимые процедуры с рамками объекта. Я бы рекомендовал создать процедуру хранения для получения данных и использовать структуру сущности для ее вызова. –