2013-03-22 2 views
10

У меня есть Measurement Объекты с соответствующими свойствами CreationTime (DateTime) и Reference (String) и некоторые другие значения.Entity Framework - запрос Linq с заказом по и группе по

Я хотел бы написать эффективный запрос LINQ к DbContext что

  • группы моих Measurement объектов по заданному Reference
  • заказов группы по либо CreationTime собственности первого Measurement из группы или среднее из CreationTime свойств
  • ограничивает запрос к самому последнему numOfEntries

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

Сам DbContext имеет DbSet<Measurement> под названием Measurements держит все Measurement объекты.

Я придумал следующий запрос, в результате которого список упорядоченных групп упорядочен, но отсутствуют некоторые группы между ними.

var groupByReference = (from m in context.Measurements 
          orderby m.CreationTime 
          group m by new { m.Reference } into g 
          select g).Take(numOfEntries).ToList(); 

Как выбрать «самые последние» группы Measurement s правильно?

Я использую Entity Framework 4.4 с базой данных MySQL (MySql Connector/Net 6.6.4). Этот пример упрощен, я могу более подробно и/или привести пример, если это необходимо.

Спасибо!

+1

Вместо расчетом «среднее значение CreationTime », рассмотрели ли вы расчет временного интервала из заданной точки и затем определение среднего значения этих временных интервалов, а затем вычисление итоговой даты на основе данной точки и среднего времени? –

ответ

0

Try переместив order by после group by:

var groupByReference = (from m in context.Measurements 
         group m by new { m.Reference } into g 
         order by g.Avg(i => i.CreationTime) 
         select g).Take(numOfEntries).ToList(); 
+0

Я пробовал это, но получил ошибку, что 'DateTime'cannot быть преобразован в' int'. Я также попытался использовать свойство 'int' для тестирования и получил сообщение MySqlException, в котором говорилось что-то вроде« Неизвестный столбец «GroupBy1.K2» в «списке полей». – zufallsfund

9

Это метод синтаксиса (который я нахожу легче читать), но это может сделать это

Обновленный Оставить комментарий

Используйте .FirstOrDefault() вместо от .First()

Что касается среднего даты, возможно, придется отказаться, что порядок на данный момент, как я не могу добраться до IDE на данный момент

var groupByReference = context.Measurements 
           .GroupBy(m => m.Reference) 
           .Select(g => new {Creation = g.FirstOrDefault().CreationTime, 
//            Avg = g.Average(m => m.CreationTime.Ticks), 
               Items = g }) 
           .OrderBy(x => x.Creation) 
//       .ThenBy(x => x.Avg) 
           .Take(numOfEntries) 
           .ToList(); 
+1

Спасибо за ваше предложение, но я получил «NotSupportedException», пытающийся определить g.First() потому что 'g' не является окончательной операцией запроса. Попытка усреднить свойство 'CreationTime' не удалась, потому что это не' int'. – zufallsfund

+0

Я обновил свой ответ, но я не смогу исправить ошибку средней даты, пока не получу IDE – NinjaNye

+0

Спасибо за ваши усилия. Я попробовал это в то же время, а также добавил свойство «Ticks», которое хранит CreationTime как длинный, так что «.Average()» должен работать. Теперь я получаю исключения MySQL, которые говорят либо «Неизвестный столбец« Distinct1.Reference »в« where clause »(FirstOrDefault), либо« Неизвестный столбец GroupBy1.K2 »в« списке полей »(Average). Является ли ошибка соединителя MySql возможной причиной этого? (Я должен упомянуть, что реальный запрос немного сложнее, я не запрашиваю DbSet напрямую, но использую другой запрос как источник.) – zufallsfund

0

Ваши требования повсюду, но это решение мое понимание из них:

к группе по справочной собственности:

var refGroupQuery = (from m in context.Measurements 
      group m by m.Reference into refGroup 
      select refGroup); 

Теперь вы говорите, вы хотите ограничить результаты по «самым последним numOfEntries» - я беру это означает, что вы хотите, чтобы ограничить возвращаемые измерения ...в этом случае:

var limitedQuery = from g in refGroupQuery 
        select new 
        { 
         Reference = g.Key, 
         RecentMeasurements = g.OrderByDescending(p => p.CreationTime).Take(numOfEntries) 
        } 

Чтобы заказать группы от первого времени создания Measurement (обратите внимание, вы должны заказать измерения, если вы хотите, самое раннее значение CreationTime, substitue «g.SomeProperty» с «g.CreationTime»):

var refGroupsOrderedByFirstCreationTimeQuery = limitedQuery.OrderBy(lq => lq.RecentMeasurements.OrderBy(g => g.SomeProperty).First().CreationTime); 

для заказа групп по среднему CreationTime, используйте свойство клещи DateTime структуры:

var refGroupsOrderedByAvgCreationTimeQuery = limitedQuery.OrderBy(lq => lq.RecentMeasurements.Average(g => g.CreationTime.Ticks)); 
1

Вы можете попробовать бросить результат GroupBy и принять в п перечислимых первый обработают остальное (здание на решении представленного NinjaNye

var groupByReference = (from m in context.Measurements 
           .GroupBy(m => m.Reference) 
           .Take(numOfEntries).AsEnumerable() 
           .Select(g => new {Creation = g.FirstOrDefault().CreationTime, 
              Avg = g.Average(m => m.CreationTime.Ticks), 
               Items = g }) 
           .OrderBy(x => x.Creation) 
           .ThenBy(x => x.Avg) 
           .ToList() select m); 

Вашего SQL-запрос будет выглядеть следующим образом (в зависимости от входа) этого

SELECT TOP (3) [t1].[Reference] AS [Key] 
FROM (
    SELECT [t0].[Reference] 
    FROM [Measurements] AS [t0] 
    GROUP BY [t0].[Reference] 
    ) AS [t1] 
GO 

-- Region Parameters 
DECLARE @x1 NVarChar(1000) = 'Ref1' 
-- EndRegion 
SELECT [t0].[CreationTime], [t0].[Id], [t0].[Reference] 
FROM [Measurements] AS [t0] 
WHERE @x1 = [t0].[Reference] 
GO 

-- Region Parameters 
DECLARE @x1 NVarChar(1000) = 'Ref2' 
-- EndRegion 
SELECT [t0].[CreationTime], [t0].[Id], [t0].[Reference] 
FROM [Measurements] AS [t0] 
WHERE @x1 = [t0].[Reference] 
Смежные вопросы