LINQ2SQL和NHibernate,按计算列分组

3
在SQL Server数据库中,我有一个记录条目的表格 - 时间戳描述
我需要在指定的时间间隔(30分钟)内获取日志发生情况。
例如:
01.01.2015 00:00 - 100
01.01.2015 00:30 - 200
01.01.2015 01:00 - 2

and so on...

What I have:

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”的异常,但未在用户代码中处理

其他信息:无法执行查询

内部异常:因为它不包含在聚合函数或GROUP BY子句中,所以列'dbo.Log.LogTimestamp'在选择列表中无效。

生成的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. Operator precedence / order is wrong in groupby clause

    datepart(minute, Log0_.LogTimestamp) / @p0 * @p1
    
  2. Select part for minutes is different than group part for minutes - select fails

我的Linq有什么问题,如何编写正确的代码?

我正在使用NHibernate build 4.0.4.GA。


在我看来,这似乎是一个错误。我已经使用LinqToSql(Entity Framework)测试了您的Linq查询,并且它运行良好。我还查看了NHibernate JIRA问题跟踪器(https://nhibernate.jira.com)中的未解决错误,但没有一个与此匹配。因此,我认为这是一个未报告的错误。 - Ismael
1个回答

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

这可能会修复它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接