Linq 执行Select时在EF Core 3中添加Day to DateTime

Linq 执行Select时在EF Core 3中添加Day to DateTime,linq,entity-framework-core,linq-to-entities,Linq,Entity Framework Core,Linq To Entities,我正在尝试使用EF Core 3查询数据库,按日期和小时对DateTime字段进行分组,并在Select上向日期添加小时部分。到目前为止,我所有的LINQ都失败了 失败案例1。使用AddHours将小时数添加到日期 Logs.GroupBy(g => new { g.DateStamp.Date, g.DateStamp.Hour, g.Result }).Select(s => new { Date = s.Key.Date.AddHours(s.K

我正在尝试使用EF Core 3查询数据库,按日期和小时对DateTime字段进行分组,并在Select上向日期添加小时部分。到目前为止,我所有的LINQ都失败了

失败案例1。使用AddHours将小时数添加到日期

Logs.GroupBy(g => new
{
    g.DateStamp.Date,
    g.DateStamp.Hour,
    g.Result
}).Select(s => new
{
    Date = s.Key.Date.AddHours(s.Key.Hour),
    s.Key.Result,
    Conversions = s.Count(),
    Cost = s.Sum(sum => sum.ConversionCost)
}).OrderBy(o => o.Date)
错误:

数据的日期函数dateadd不支持datepart hour 键入日期

不确定问题的确切位置,Linq不支持AddHours to Entity provider或s.Key.Date字段不能再包含小时,因为它成为仅日期字段

失败案例2。创建新的DateTime对象并传递变量

Logs.GroupBy(g => new
{
    g.DateStamp.Date,
    g.DateStamp.Hour,
    g.Result
}).Select(s => new
{
    Date =new DateTime(s.Key.Date.Year, s.Key.Date.Month, s.Key.Date.Day,  s.Key.Hour, 0, 0),   
    s.Key.Result,
    Conversions = s.Count(),
    Cost = s.Sum(sum => sum.ConversionCost)
}).OrderBy(o => o.Date)
错误:

InvalidOperationException:LINQ表达式 “OrderBy( 来源:选择f\uu AnonymousType0,Log>,f\uu AnonymousType1>( 来源:GroupByf\uuu匿名类型0,日志>( 资料来源:DbSet, 键选择器:(l)=>新{ 日期=l.DateStamp.Date, 小时=l.DateStamp.Hour, 结果=l.结果 }, 元素选择器:(l)=>l), 选择器:(e)=>new{ 日期=新日期时间( e、 Key.Date.Year, e、 Key.Date.Month, e、 Key.Date.Day, e、 关键时刻, 0, 0 ), 结果=e.Key.Result, 换算=计数(e), 成本=总和( 资料来源:e, 选择器:(sum)=>sum.ConversionCost) }), 无法转换keySelector:(e0)=>e0.Date)“。以可以翻译的形式重写查询,或者切换到 通过插入一个调用 AsEnumerable()、AsAsAsyncEnumerable()、ToList()或ToListSync()。看见 了解更多信息

OrderBy(o=>o.Date)
停止工作并给出异常,为什么?我也不知道


最后一个问题是,如何使用EF Core按日期+小时对SQL数据库中的DateTime字段进行分组,并将其移动到一个字段中进行选择,并在最后执行按新日期字段排序。

我可以对失败案例1进行评论,因为我也遇到了同样的问题

  • x.Date
    转换为sql作为
    CONVERT(Date,x)
  • x.AddHours(y)
    转换为sql作为
    DATEADD(hour,x,y)
  • 我们两者都有,所以它是
    DATEADD(hour,CONVERT(date,x),y)
    ,这是不可能的,因为您不能将小时添加到
    date
    类型的数据中,因此会出现错误消息
  • 在sql级别上,它通常通过向
    datetime2
    添加额外的强制转换来修复,例如

    CAST(CONVERT(date, x) AS datetime2)
    
    因此,您可以再次处理
    datetime2
    级别,并能够在结果值中添加小时数

    尽管如此,我不知道如何强制EF生成额外的强制转换(无论是
    (DateTime)
    还是
    Convert.ToDateTime
    都没有帮助),因此我提出了一个解决方法(不能说它是否会因溢出而失败一次)

    使用EF Core 3.1.12对其进行了测试,结果与预期相符。这是输出

    (DATEADD(
        hour, 
        CAST(y AS int), 
        DATEADD(
            millisecond, 
            CAST(
                CAST(
                    -DATEDIFF(MILLISECOND, '00:00:00', CAST(x AS time)) AS float) AS int
                ), 
            x
        )
    )
    

    我猜案例2失败了,因为EF无法翻译
    new DateTime
    表达式,但这只是一个含糊不清的错误。

    您能否指定日志中的内容以及在所述OrderBy之后您的目标是什么?通常情况下,这种方式与案例1类似。正如您所看到的,efcore转换为SQL。运行时异常应该来自数据库,并且看起来基础数据库表列类型是date,它没有时间部分。因此,您的查询对于这种类型的列没有意义(
    value.Date==value
    value.Hour==0
    )。
    (DATEADD(
        hour, 
        CAST(y AS int), 
        DATEADD(
            millisecond, 
            CAST(
                CAST(
                    -DATEDIFF(MILLISECOND, '00:00:00', CAST(x AS time)) AS float) AS int
                ), 
            x
        )
    )