【发布时间】: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.Now和DateAdd=>DateTime.AddXyz(Xyz:Hours,Minutes等)
标签: sql-server linq entity-framework-core