2015-11-20 99 views
3

在SQL Server數據庫中,我有一個包含日誌條目 - timestampdescription的表。LINQ2SQL和NHibernate,按計算列分組

我需要以指定的時間間隔(30分鐘)獲得日誌的發生。

如:

01.01.2015 00:00 - 100 
01.01.2015 00:30 - 200 
01.01.2015 01:00 - 2 

等等...

我有什麼:

var logs = session.Query<Log>; 

//... other operations on logs queryable 

var intervalInMinutes = 30; 
var logsFrequency = logs 
    .GroupBy(l => new 
    { 
     Year = l.LogTimestamp.Year, 
     Month = l.LogTimestamp.Month, 
     Day = l.LogTimestamp.Day, 
     Hour = l.LogTimestamp.Hour, 
     Minute = (l.LogTimestamp.Minute/intervalInMinutes) * intervalInMinutes, 
    }) 
    .Select(g => new LogsOccurence() 
    { 
     StartingDatetime = new DateTime(g.Key.Year, g.Key.Month, g.Key.Day, g.Key.Hour, g.Key.Minute, 0), 
     Frequency = g.Count() 
    }) 
    .ToList(); 

以下查詢失敗:

類型的異常「的NHibernate .Exceptions.GenericADOException'發生在NHibernate中.dll文件,但不是在用戶代碼來處理

其他信息:無法執行查詢

內部異常:因爲它不是在聚合載列「dbo.Log.LogTimestamp」在選擇列表中無效函數或GROUP BY子句。

生成的select語句是:

select 
    datepart(year, Log0_.LogTimestamp) as col_0_0_ 
    , datepart(month, Log0_.LogTimestamp) as col_1_0_ 
    , datepart(day, Log0_.LogTimestamp) as col_2_0_ 
    , datepart(hour, Log0_.LogTimestamp) as col_3_0_ 
    , datepart(minute, Log0_.LogTimestamp) as col_4_0_ 
    , cast(count(*) as INT) as col_5_0_ 
from 
    dbo.[Log] Log0_ 
group by 
    datepart(year, Log0_.LogTimestamp) 
    , datepart(month, Log0_.LogTimestamp) 
    , datepart(day, Log0_.LogTimestamp) 
    , datepart(hour, Log0_.LogTimestamp) 
    , datepart(minute, Log0_.LogTimestamp)/@p0*@p1 
Name:p1 - Value:30 Name:p2 - Value:30 
  1. 運算符優先級/順序是錯誤的groupby條款

    datepart(minute, Log0_.LogTimestamp)/@p0 * @p1 
    
  2. 幾分鐘選擇部分比幾分鐘組部分不同 - 選擇失敗

我的Linq有什麼問題,以及如何編寫正確的?

我正在使用NHibernate生成4.0.4.GA.

+0

它看起來像一個bug。我已經使用LinqToSql(Entity Framework)測試了你的Linq查詢,並且它工作正常。我還查看了NHibernate JIRA問題跟蹤器(https://nhibernate.jira.com)中是否存在漏洞,但似乎沒有人能夠匹配這個漏洞。所以,我認爲這是一個未報告的錯誤。 – Ismael

回答

0

運算符優先級/順序是錯誤的GROUPBY子句

運算符優先級看起來是正確的給我。在C#T-SQL中,乘法和除法具有相同的優先級。因此...

datepart(minute, Log0_.LogTimestamp)/@p0 * @p1 

...等價於...

(datepart(minute, Log0_.LogTimestamp)/@p0) * @p1 

選擇一部分分鐘要比分鐘組部分不同 - 選擇失敗。

它在LINQ查詢中也有所不同。由於GroupBy已...

Minute = (l.LogTimestamp.Minute/intervalInMinutes) * intervalInMinutes, 

...,在Select也應該有......

g.Key.Minute/intervalInMinutes * intervalInMinutes 

這有可能會解決它。