linq 执行Select时,在EF Core 3中将日期添加到DateTime

p8h8hvxi  于 2022-12-06  发布在  其他
关注(0)|答案(2)|浏览(184)

我尝试使用EF Core 3查询数据库,按日期和小时对日期时间字段进行分组,并在选择时将小时部分添加到日期。到目前为止,我的所有Linqs都失败了。
失败案例1。使用AddHours将小时数添加到Date。

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)

错误:
数据类型为date的日期函数dateadd不支持日期部分hour。
不确定问题的确切位置,Linq to Entity提供程序或s.Key不支持AddHours。日期字段不能再包含小时,因为它变成了仅限日期的字段。
失败情况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)

错误:
无效操作异常错误:LINQ表达式'OrderBy〈〈〉f__AnonymousType1,DateTime〉(源代码:选择匿名类型0、日志、匿名类型1(源:GroupByf__匿名类型0,日志〉(源:数据集,键选择器:(l)=〉new {日期= l.日期戳.日期,小时= l.日期戳.小时,结果= l.结果},元素选择器:(l)=〉l),选择器:(e)=〉new {日期=新日期时间(e.关键字.日期.年,e.关键字.日期.月,e.关键字.日期.日,e.关键字.小时,0,0),Result = e.关键字.结果,转换= Count(e),Cost = Sum(源:e、选择器:(总计)=〉总计.转换成本)}),键选择器:(e0)=〉e0.Date)'无法转换。请以可转换的形式重写查询,或者通过插入对AsEnumerable()、AsAsyncEnumerable()、ToList()或ToListAsync()的调用来显式切换到客户端计算。有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038
OrderBy(o => o.Date)停止工作并给出异常,为什么?我也不知道。
因此,最后一个问题是,如何使用EF Core按日期+小时对SQL数据库中的DateTime字段进行分组,并将其移动到Select中的一个字段中,同时在最后按新的日期字段执行OrderBy。

vecaoik1

vecaoik11#

我能够对失败案例1进行评论,因为我也遇到过相同的问题。
1.将x.Date转换为sql,格式为CONVERT(date, x)
1.将x.AddHours(y)转换为sql,格式为DATEADD(hour, x, y)
1.我们有两个,所以它是DATEADD(hour, CONVERT(date, x), y),这是不可能的,因为你不能添加小时到类型为date的数据,因此出现错误消息。
在sql级别上,通常通过向datetime2添加额外的强制类型转换来修复,例如

CAST(CONVERT(date, x) AS datetime2)

因此,您可以再次在datetime2级别上进行交易,并能够将小时数添加到结果值中。
我已经说过,我不知道如何强制EF生成额外的强制转换((DateTime)Convert.ToDateTime都没有帮助),所以这里是我想出的一个解决方案(不能说它是否会因溢出而失败)

x.AddMilliseconds(-EF.Functions.DateDiffMillisecond(TimeSpan.Zero, x.TimeOfDay))
    .AddHours(y)

用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表达式,但这只是一个隐含的错误。

iqxoj9l9

iqxoj9l92#

我在使用EFCore 6时遇到了同样的问题,我在执行Date.AddHours时遇到了错误,因为它看起来像是转换为date而不是datetime。为了使它工作,我必须先转换为object,然后再转换为DATETIME,然后我才能添加小时数。

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

相关问题