在LINQ to EF查询中防止'NOW()'

时间:2012-05-21 21:13:57

标签: mysql linq linq-to-entities

更新:我的原始问题无效,因为我误读了MySql日志。抱歉。请参阅下文,更新。

我正在使用LINQ查询:

var homework = ctx.Threads.Where(t => t.ClassName == "10L"
                                   && t.EndDate != null
                                   && t.StartDate <= DateTime.Now
                                   && t.EndDate > DateTime.Now)
                          .OrderByDescending(o => o.EndDate)
                          .FirstOrDefault();

这将创建SQL(MySQL 5.5.14):

SELECT
`Project1`.`id`,
`Project1`.`title`,
`Project1`.`startdate`,
`Project1`.`enddate`,
`Project1`.`class`,
`Project1`.`body`,
`Project1`.`threadtype`
FROM (SELECT
     `Extent1`.`id`,
     `Extent1`.`title`,
     `Extent1`.`startdate`,
     `Extent1`.`enddate`,
     `Extent1`.`class`,
     `Extent1`.`body`,
     `Extent1`.`threadtype`
     FROM
     `threads` AS `Extent1`
     WHERE (((`Extent1`.`class` = '10L')
         AND (`Extent1`.`enddate` IS NOT NULL))
         AND (`Extent1`.`startdate` <= (NOW())))
         AND (`Extent1`.`enddate` > (NOW())))
AS `Project1`
ORDER BY `Project1`.`enddate` DESC
LIMIT 1

LINQ to EF如何知道使用NOW()函数?当然,我只是按值传递一个普通的DateTime结构?

如果我使用var now = DateTime.Now;然后在LINQ查询中使用now变量,则日期将作为文字传递。发生了什么事?

3 个答案:

答案 0 :(得分:4)

LINQ-to-whatever通过解析表达式树来从.NET代码转换为适当的SQL语言。这允许查询尽可能多地处理数据库端而不是客户端。结果,当你说:

... myField <= DateTime.Now

解析器使用表达式引用DateTime.Now,而不进行评估,以便尽可能地将代码转换为适当的SQL语言。这是允许LINQ高效工作的原因,但作为副作用,查询中的所有被解释为表达式并尝试转换为适当的SQL代码。当您将其存储在变量中时,如:

var now = DateTime.Now;

立即评估该值并将其存储到now中,该值将在您的查询中使用,而不是表达式。

答案 1 :(得分:3)

DateTime.Now是一个函数(Now属性的getter),所以linq2EF在尝试创建表达式树时会将其视为函数。这就像是说.ToString()在link2EF中是如何工作的。此外,当您从临时变量中使用它时,它将被视为临时变量,就像将.ToString()的结果保存在临时变量中一样,最终更改不会影响您的输出。

答案 2 :(得分:0)

好问答。我只是想在我的环境中添加它,它使用Microsoft SQL Server 2008 R2,在LINQ to Entities查询中引用DateTime.Now会生成以下SQL表达式:

CAST( SysDateTime() AS datetime2)

我相信这与在MySQL中生成NOW()类似,因此无论底层数据库如何,都会看到相同的行为。

当然,如果您希望运行LINQ代码的本地时间而不是数据库服务器,则此行为可能会出现问题。将DateTime.Now分配给局部变量并在LINQ表达式中使用它的解决方法与MS SQL一样正常,正如预期的那样。