执行"选择"时,在 EF Core 3 中将"日期"添加到"日期时间&



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

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

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)

错误:

日期函数不支持日期部分小时 日期为数据添加 键入日期。

不确定问题出在哪里,Linq 到实体提供程序不支持 AddHours 或 s.Key.Date 字段不能再包含小时数,因为它变成了仅日期字段。

失败案例 2。创建新的日期时间对象并传递变量。

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>( 来源: Selectf__AnonymousType0, 日志>, <>f__AnonymousType1>( 来源: GroupByf__AnonymousType0, 日志>( 来源: 数据库集, 键选择器: (l( => new { Date = l.DateStamp.Date, 小时 = l.日期戳.小时, 结果 = l.结果 }, 元素选择器: (l( => l(, 选择器: (e( => 新 { 日期 = 新的日期时间( e.key.date.year, e.Key.Date.Month, e.Key.Date.Day, e.Key.Hour, 0, 0 ), 结果 = e.key.result, 转化次数 = 计数(e(, 成本 = 总和( 资料来源:E, 选择器:(总和(=>总和。转换成本( }), 键选择器: (e0( => e0.日期("无法翻译。以可翻译的形式重写查询,或切换到 通过插入对任一 AsEnumerable((, AsAsyncEnumerable((, ToList(( 或 ToListAsync((。看 https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

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

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

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

  1. x.Date将转换为 SQL 作为CONVERT(date, x)
  2. x.AddHours(y)将转换为 SQL 作为DATEADD(hour, x, y)
  3. 我们两者都有,所以它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表达式,但这只是错误是神秘的。

我在使用 EFCore 6 时遇到了同样的问题,我在执行 Date.AddHours 时遇到错误,因为它看起来像是投射到日期而不是日期时间。为了让它工作,我必须投射到对象,然后投射到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)

最新更新