抱歉,这可能是个糟糕的标题;我有一个问题更多是出于好奇。
我测试了以两种不同方式编写的相同 LINQ to Entities 语句,一种使用 Datetime.Now,另一种使用日期变量:
var timeNow = DateTime.Now;
var pendingMailshots = db.MailshotHistoryDatas.Where(m =>
m.SendDate < timeNow).ToList();
var pendingMailshots = db.MailshotHistoryDatas.Where(m =>
m.SendDate < DateTime.Now).ToList();
我注意到他们找到的数据存在差异,经过一些挖掘和分析后我发现了这一点:
exec sp_executesql N'SELECT
[Extent1].[MailshotGuid] AS [MailshotGuid],
[Extent1].[MailshotLineId] AS [MailshotLineId],
[Extent1].[SendDate] AS [SendDate],
[Extent1].[MessageType] AS [MessageType],
[Extent1].[SendStatus] AS [SendStatus],
[Extent1].[Recipients] AS [Recipients],
[Extent1].[SendAttempts] AS [SendAttempts],
[Extent1].[DateSent] AS [DateSent]
FROM [dbo].[MailshotLineDatas] AS [Extent1]
INNER JOIN [dbo].[MailshotDatas] AS [Extent2] ON [Extent1].[MailshotGuid] = [Extent2].[MailshotGuid]
WHERE ([Extent1].[SendDate] < @p__linq__0),N'@p__linq__0 datetime2(7),@p__linq__0='2018-01-04 15:11:26.5618636'
SELECT
[Extent1].[MailshotGuid] AS [MailshotGuid],
[Extent1].[MailshotLineId] AS [MailshotLineId],
[Extent1].[SendDate] AS [SendDate],
[Extent1].[MessageType] AS [MessageType],
[Extent1].[SendStatus] AS [SendStatus],
[Extent1].[Recipients] AS [Recipients],
[Extent1].[SendAttempts] AS [SendAttempts],
[Extent1].[DateSent] AS [DateSent]
FROM [dbo].[MailshotLineDatas] AS [Extent1]
INNER JOIN [dbo].[MailshotDatas] AS [Extent2] ON [Extent1].[MailshotGuid] = [Extent2].[MailshotGuid]
WHERE([Extent2].[StartDate] < (SysDateTime())))
它使用 datetime 变量将查询作为存储过程运行,并使用 Datetime。现在它将代码转换为 TSQL。
谁能解释一下这是为什么? 另外,您认为什么是更好的做法?
提前致谢, 亚当
最佳答案
您正在定义一个将在稍后执行的表达式。
第一个 LINQ 表达式包含一个用特定值 (DateTime.Now) 初始化的 DateTime 变量。但是,在执行表达式时,该变量将不再具有当前日期的值。因此,在实际执行表达式时会使用一个参数。
在后一种情况下,您指定一个查询,其中过滤器子句必须使用当前日期/时间。由于表达式是延迟执行的,引擎不知道你什么时候真正执行它,所以它使用特定于数据库的函数来获取当前日期和时间。
对于这种情况,没有“什么是更好的做法”这样的事情。这完全取决于您的用例。 此行为仅特定于 LINQ 查询的延迟执行:您实际上是在构建一个表达式,该表达式只会在您调用 ToList()/ToArray 等时执行...
当您将代码重写为如下内容时:
var timeNow = DateTime.Now;
var query = db.MailshotHistoryDatas.Where(m =>
m.SendDate < timeNow);
var pendingMailshots = query.ToList();
在上面的示例中,查询只会在您调用 query.ToList();
的代码行执行
由于您可能会构建表达式并稍后在程序中执行它,因此 LINQ 必须使用带有参数的查询来确保将正确的日期和时间传递给该查询,从而传递给您定义的变量。
关于c# - LINQ to Entities 以不同方式使用日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48098587/