c# - LINQ to Entities 以不同方式使用日期时间

标签 c# sql entity-framework linq stored-procedures

抱歉,这可能是个糟糕的标题;我有一个问题更多是出于好奇。

我测试了以两种不同方式编写的相同 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/

相关文章:

c# - 在一笔事务中删除 Azure blob

entity-framework - AutoMapper - 尝试在运行时将变量从 WEB API Controller 传递到 Automapper 配置

c# - 我可以在 ASP :Button? 的 Text 属性中放置一个 <span> 标签吗

c# - 不可变与可变 C#

c# - 通过 Web 代理与 WCF 服务通信;从 Windows 服务中

sql - 我如何计算一个月内不在前一个月的用户数?

sql - 如何选择字段名称包含点的列

mysql - 如何从 SQL 查询中获取随机行?

c# - 如何将 MySQL 与 .NET Core 3 和 Entity Framework 6 集成

c# - CompiledQuery 与普通 Linq SQL 生成