2013-03-22 46 views
10

我有Measurement具有相關屬性的對象CreationTime(DateTime)和Reference(String)以及其他一些值。實體框架 - Linq查詢,按順序排列並且組編號爲

我想用一個給定的Reference

  • 訂單的有效LINQ查詢寫入DbContext

    • 組我Measurement對象從該組的團體由第一MeasurementCreationTime物業或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組?

    我使用實體框架4.4與MySQL數據庫(MySql連接器/網絡6.6.4)。這個例子被簡化了,如果需要的話,我可以進入更多的細節和/或給出一個例子。

    謝謝!

  • +1

    而不是計算「的創建時間的平均「,您是否考慮過從給定點計算時間跨度,然後確定這些時間跨度的平均值,然後根據給定點和平均時間跨度計算結果日期? – 2013-03-22 19:52:17

    回答

    0

    嘗試移動order bygroup 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'不能轉換爲'int'。我也用'int'屬性進行了測試,得到了一個MySqlException異常,如'字段列表'中的未知列'GroupBy1.K2'「 – zufallsfund 2013-03-22 14:07:07

    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 2013-03-22 14:29:50

    +0

    我已經更新了我的答案,但我無法修復平均日期問題,直到遇到IDE – NinjaNye 2013-03-22 18:50:39

    +0

    感謝您的努力。在此期間我嘗試了這種方法,並添加了一個「Ticks」屬性,該屬性將CreationTime存儲爲一個很長的時間,以便'.Average()'能夠正常工作。現在,我正在獲取MySQL異常,其中說明了'場列表'(平均)'中的'where子句''(FirstOrDefault)或'未知列'GroupBy1.K2'中的未知列'Distinct1.Reference'。是一個MySql連接器錯誤的可能原因呢? (我應該提到真正的查詢有點複雜,我不直接查詢DbSet,而是使用另一個查詢作爲源。) – zufallsfund 2013-03-26 10:01:24

    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) 
            } 
    

    要訂購的第一次測量創建時間組(注意:您應該測量;如果你想最早的創建時間值,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]