EF MySQL中ToQueryString生成时间减法SQL异常问题咨询
问题解答
1. ToQueryString输出的问题根源
你看到的ToQueryString输出SQL确实存在逻辑错误:在MySQL中,CURRENT_TIMESTAMP() - @__t_0这种写法不会按预期的“时间减去时长”计算。MySQL会将CURRENT_TIMESTAMP()和TIME类型变量转换成数值(比如把时间转成YYYYMMDDHHMMSS格式的数字)再做减法,结果完全不是你想要的“当前时间往前推10小时”,导致过滤条件几乎失效。
2. 正确的MySQL SQL写法
要实现“CreatedAt小于当前时间减10小时”的逻辑,正确的MySQL SQL有两种写法:
- 使用
DATE_SUB函数:
SELECT t.Id, t.CreatedAt, t.Status FROM table1 AS t WHERE (t.Status = 3) AND (t.CreatedAt < DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 10 HOUR));
- 直接使用INTERVAL语法:
SELECT t.Id, t.CreatedAt, t.Status FROM table1 AS t WHERE (t.Status = 3) AND (t.CreatedAt < CURRENT_TIMESTAMP() - INTERVAL 10 HOUR);
如果要参数化时长,需将时长作为INTERVAL的参数传递,而非TIME类型变量,示例:
SET @__hours_0 = 10; SELECT t.Id, t.CreatedAt, t.Status FROM table1 AS t WHERE (t.Status = 3) AND (t.CreatedAt < DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL @__hours_0 HOUR));
3. 为什么C#代码执行结果正确
EF Core实际执行查询时,并没有采用ToQueryString输出的错误逻辑。它会在客户端先计算出DateTime.Now - t的具体DateTime值(比如当前时间是2024-05-20 15:00:00,计算后得到2024-05-20 05:00:00),再将这个具体值作为参数传递给MySQL,实际执行的SQL类似:
SET @__nowMinusT_0 = '2024-05-20 05:00:00'; SELECT t.Id, t.CreatedAt, t.Status FROM table1 AS t WHERE (t.Status = 3) AND (t.CreatedAt < @__nowMinusT_0);
这种参数化方式避免了MySQL端的错误时间减法运算,因此结果正确。ToQueryString的输出只是SQL的近似表示,并未准确反映EF Core实际执行时的参数化处理逻辑。
内容的提问来源于stack exchange,提问作者Mehrdad
相关产品推荐
相关产品推荐

