如何在EF Core中提取DateTime小时并筛选非7-21点的数据?
问题描述
技术栈:
- EFCore (7.0.5)
- ASPNetCore (7.0.0)
- Pomelo.EFCore.Mysql (7.0.0)
现有一段从表中获取数据的代码:
var v = await _dbContext.HistoLogs! .Where(h => h.Datecre > DateTime.Today.AddDays(-31)) .ToListAsync();
这段代码可正常运行,但需要**排除7:00到21:00(早7点到晚9点)**的数据。
已能用MySQL语句实现该需求:
SELECT EXTRACT(HOUR FROM h.Datecre), h.Datecre, h.`Action` from myschema.HistoLogs h WHERE Datecre > DATE_SUB(NOW(), INTERVAL 31 DAY) AND (EXTRACT(HOUR FROM h.Datecre) BETWEEN 22 AND 23 OR EXTRACT(HOUR FROM h.Datecre) BETWEEN 0 AND 6)
但不清楚如何在EF Core中实现对应查询,尝试了以下代码但未生效,求正确写法:
var v = await _dbContext.HistoLogs! .Where(h => h.Datecre > DateTime.Today.AddDays(-31)) .Where(h => h.Datecre.Hour < 7) .Where(h => h.Datecre.Hour > 21) .ToListAsync();
正确写法
你之前的代码问题在于连续使用两个Where,这要求数据同时满足Hour <7 并且 Hour>21——显然没有符合这个条件的时间,逻辑错误。
正确逻辑应该是或的关系,把两个条件合并到同一个Where中,用||连接:
var v = await _dbContext.HistoLogs! .Where(h => h.Datecre > DateTime.Today.AddDays(-31) && (h.Datecre.Hour < 7 || h.Datecre.Hour > 21)) .ToListAsync();
Pomelo.EFCore.Mysql会自动将h.Datecre.Hour转换为MySQL的EXTRACT(HOUR FROM Datecre),最终生成的SQL和你手动编写的逻辑完全一致,能正确筛选出非7-21点的数据。
如果想和原生SQL里的DATE_SUB(NOW(), INTERVAL 31 DAY)完全对应(前者是数据库当前时间往前推31天,而DateTime.Today.AddDays(-31)是本地今天0点往前推31天),可以改用EF的数据库端时间函数:
var v = await _dbContext.HistoLogs! .Where(h => h.Datecre > EF.Functions.Now().AddDays(-31) && (h.Datecre.Hour < 7 || h.Datecre.Hour > 21)) .ToListAsync();
内容的提问来源于stack exchange,提问作者Tanc
相关产品推荐
相关产品推荐

