在Lambda表达式中如何将日期转为Ticks实现时间范围查询
EF Core 使用Ticks进行日期筛选的解决方案
错误原因
EF Core 无法将DateTime.Ticks属性的读取操作翻译为对应的SQL语句,因此无法在数据库侧执行该过滤逻辑,才会抛出要求切换客户端求值的报错。
最优解决方案(推荐)
不要在查询中使用Ticks做比较,直接将起止参数解析为DateTime类型后做直接比较,EF Core原生支持该操作的SQL翻译,还可以利用数据库的日期索引提升查询性能,代码示例如下:
// 解析起止参数为DateTime类型 DateTime startDate = DateTime.Parse(checklistReport.StartdateHsrch); DateTime endDate = DateTime.Parse(checklistReport.EnddateHsrch); // 直接做日期比较,可被EF Core正常翻译为SQL var reportResult = _context.ChecklistReports.Where(e => e.RequestDateGregorianHsrch >= startDate && e.RequestDateGregorianHsrch <= endDate ).ToList(); return reportResult;
注意:如果你的查询参数仅传入日期(无时间部分),且需要包含结束日期当天的所有数据,可以将结束日期调整为DateTime.Parse(checklistReport.EnddateHsrch).AddDays(1).AddTicks(-1),避免过滤掉结束日期当天带时间部分的数据。
必须使用Ticks的场景方案
如果业务逻辑要求必须基于Ticks做筛选,可以选择以下两种方案:
- 方案1:新增数据库计算列(性能最优)
给ChecklistReports表新增持久化计算列,存储RequestDateGregorianHsrch对应的Ticks值,将该计算列映射到实体类的long?类型属性,后续直接筛选该属性即可被EF Core正常翻译为SQL,不会触发报错。 - 方案2:客户端评估(仅适合数据量极小的场景)
先将数据拉取到内存后再做Ticks筛选,数据量大时会有严重性能问题,代码示例如下:
var StartdateHsrch = DateTime.Parse(checklistReport.StartdateHsrch).Ticks; var EnddateHsrch = DateTime.Parse(checklistReport.EnddateHsrch).Ticks; // 先调用AsEnumerable切换到客户端求值 var reportResult = _context.ChecklistReports .AsEnumerable() .Where(e => e.RequestDateGregorianHsrch.HasValue && e.RequestDateGregorianHsrch.Value.Ticks >= StartdateHsrch && e.RequestDateGregorianHsrch.Value.Ticks <= EnddateHsrch ).ToList(); return reportResult;
内容的提问来源于stack exchange,提问作者Mohammad Naghsh
相关产品推荐
相关产品推荐

