【问题标题】:LINQ query not statisfying the datetime validationLINQ 查询未统计日期时间验证
【发布时间】:2021-03-24 20:04:31
【问题描述】:

这是我返回匹配记录的 LINQ

var staffawards = await _context.StaffAwards.FirstOrDefaultAsync(c => c.StaffID == StaffAwards.StaffID && c.EmpID == StaffAwards.EmpID && c.AwardDate == StaffAwards.AwardDate);

StaffAwards.AwardDate 的格式为“09/12/2020 12:00:00 AM” 而我表中的 AwardDate 将是这样的“2020-12-09 17:16:00.000”

如何在 Sql Server 日期时间中转换 StaffAwards.AwardDate? AnyHelp 将不胜感激。

【问题讨论】:

  • 1 不要将日期/时间字符串表示与实际存储格式混淆:.NET 和 SQL Server 都不会将日期/时间存储为字符串。您发布的是字符串表示形式。 2.AwardDate使用什么字段类型? 3. 你真的需要比较日期/时间吗,或者日期比较就足够了?
  • SQL Server 和 C# 都有本机 DateTime 类型(SQL Server 有其他时间和日期类型)。这些类型没有格式,除非您将它们转换为字符串(在这种情况下,您可以将它们转换为任何格式)。如果您的 StaffAwards.AwardDate 是字符串,请使用 Parse 或 TryParse(或它们的 Exact 等效项 将其转换为 DateTime
  • 嗨@Dennis,StaffAwards.AwardDate 的数据类型是 Datetime,因为我使用 datetimepicker,所以输入字段类型是 Text。我只是想检查表值是否等于用户输入值。

标签: c# entity-framework asp.net-core linq-to-sql razor-pages


【解决方案1】:

要将日期与数据库格式一起使用,您可以使用 DbFunctions。

像这样:

var staffawards = await _context.StaffAwards.FirstOrDefaultAsync(c => c.StaffID == StaffAwards.StaffID && c.EmpID == StaffAwards.EmpID && DbFunctions.TruncateTime(DateTime.Parse(c.AwardDate)) == StaffAwards.AwardDate);

重要提示:对于 TruncateTime,您必须使用 DateTime。您必须将 c.AwardDate 转换为 DateTime。 DateTime.Parse(c.AwardDate)

【讨论】:

  • 嗨@Presi,当我将我的查询更改为您的查询时,它显示“DbFunction 不包含 TruncateTime 的定义”,并且 c.AwardDate iis 也显示一些错误,如“参数 1:无法转换表单系统。日期时间到 System.ReadOnlySpan'
  • 您的代码中有using System.Data.Entity; 吗?那么它应该可以工作了。
【解决方案2】:

很可能,您将 SQL 服务器安装在单独的计算机上,这可能是由于日期格式不同。

但是不需要这种转换,实体框架会自动为你做。 如果你只是比较日期,你可以使用这个代码:

var staffawards = await _context.StaffAwards.FirstOrDefaultAsync(c => c.StaffID == StaffAwards.StaffID && c.EmpID == StaffAwards.EmpID && c.AwardDate.Date == StaffAwards.AwardDate.Date);

【讨论】:

  • 嗨@Ramil Aliyev,目前执行的sql查询显示如下 - SELECT * FROM StaffAwards Where StaffID='19' AND EmpID='12345678' AND AwardDate='09/12/2020 12: 00:00 AM' - 返回一个空的结果集。
  • 我在 SSMS 中执行了相同的查询,但做了一些更改 - SELECT * FROM StaffAwards Where StaffID='19' AND EmpID='12345678' AND AwardDate='2020-12-09 17:16:00.000 ' - 这将输出一条记录
  • @Teena 数据库中的AwardDate列类型是datetime还是nvarchar?
  • 嗨@Ramil Aliyev,列类型是日期时间
【解决方案3】:

如果您的代码和数据库按应有的方式使用 Date/DateTime 类型,而不是字符串,那么您需要了解以下几点:

  • 日期数据类型没有格式,只有从日期创建的字符串有格式。您在代码/sql 查询工具中看到的任何格式都是它在向您显示日期时应用的格式(它必须将其转换为字符串才能显示)
  • 具有午夜时间的日期时间与时间为 17:16 的日期时间完全不同,就像数字 1.0 与 1.75352 完全不同一样;如果您使用 equals 并传递除午夜以外的任何时间,您将永远不会让数据库返回一个午夜时间的记录,就像您永远不会通过询问获得一个人的年龄为 1.0 的记录一样“其中年龄 = 1.75352”

要么修正你的参数,让它像 db 一样是午夜,要么使用参数范围(如果 db 中的日期还有其他时间)

//if the db date is always midnight
.Where(x => x.DateColumnInDb == datetimeParameter.Date);

//if the db might have times too
.Where(x => x.DateColumnInDb >= datetimeParameter.Date && x.DateColumnInDb < datetimeParameter.Date.AddDays(1));

通过使用范围,我们不会冒险要求数据库在每次查询时都转换表中的每个日期时间。在 where 子句中转换数据通常是一个坏主意,因为它通常会导致显着的性能损失,因为无法使用索引

另外,请确保您的 .net 端日期时间和数据库时间使用相同的时区,否则它们实际上指的是不同的时间

【讨论】:

  • 嗨@Caius Jard,非常感谢您的详细解释
猜你喜欢
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多