如何在 EF Core 和 LINQ 中表达 GetDate() 和 DateAdd() 方法?

Posted

技术标签:

【中文标题】如何在 EF Core 和 LINQ 中表达 GetDate() 和 DateAdd() 方法?【英文标题】:How can I express GetDate() and DateAdd() methods in EF Core and LINQ? 【发布时间】:2019-04-04 18:14:54 【问题描述】:

我正在使用 SQL Server 和 Entity Framework Core 2。我有以下 SQL 查询(在 SQL Server Management Studio 中)正确地为我提供了前一小时添加的测量值(到测量值表中):

SELECT id, [timestamp] 
FROM measurement 
WHERE
  dateADD(MINUTE, 60, [timestamp]) > getdate()

这很好用。但现在我想使用 EF Core 2 在 LINQ 中编写此查询。 当然我可以写如下代码:

dbContext
   .Measurement
   .Include(m => m.Section)
   .GroupBy(m => m.Section, (section, m) => new Section
    
       Name = section.Name,
       CustomerId = section.CustomerId,
       MostRecentMeasurement = m.Max(z => z.Timestamp)
    )
   .Where(x => x.MostRecentMeasurement > DateTime.Now.AddHours(-1))
   .ToList();

但这有以下缺点:

DateTime.Now 无法转换为 SQL,因此将在执行不佳的客户端进行评估, 客户端的时区与数据库服务器的时区不同,需要额外的复杂性和计算。

如何在 EF Core 中表达查询,使其可以完全转换为 SQL?

【问题讨论】:

您使用的是哪个确切的 EF Core 版本? DateTime.Now.AddHours(-1) 在最新的 EF Core 2.2.3 中完美转换为 DATEADD(hour, -1.0E0, GETDATE()) 我使用的是 2.1.8。我被日志消息触发:“Microsoft.EntityFrameworkCore.Query:Warning: The LINQ expression 'where (from Measurement z in [x] select [z].Timestamp => Max() > DateTime.Now.AddHours( -1))' 无法翻译,将在本地进行评估。”升级到2.2.3后也是这样 那么问题可能出在Max。有时间我去看看。同时,您可以验证它不会在“正常”Where 中发生(不涉及GroupBy 抱歉,我无法使用提供的查询重现。我试图重建实体模型,但查询给了我“忽略包含”警告和“必须是可简化节点”异常。删除Include 并将GroupBy(m => m.Section 更改为GroupBy(m => new m.Section.Name, m.Section.CustomerId 允许我运行它,并且它已完全转换为SQL。因此,要找到您的代码的具体问题,我们需要minimal reproducible example,但原始问题的一般答案是GETDATE() => DateTime.NowDateAdd => DateTime.AddXyz (Xyz: HoursMinutes 等) 【参考方案1】:

DateTime.Now.AddHours(-1) 在 EF Core 5.0.8 中完美转换为 DATEADD(hour, -1.0E0, GETDATE())。

(注意,我复制了 Ivan Stoev 的评论,因为它回答了我的类似问题。)

【讨论】:

以上是关于如何在 EF Core 和 LINQ 中表达 GetDate() 和 DateAdd() 方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ 和 EF Core 进行一对多

如何在 GraphQL 中表达输入验证

如何将带有 LEFT JOIN 的 SQL 转换为 EF CORE 3 LINQ

连续获取最大值时如何解决错误(EF Core Linq)? [复制]

无法从 Linq 查询 EF Core 访问字段值

使用 linq 计算 EF Core 中的平均评分