从 Web API 服务器在 linq 中查询时数据库混淆中的 UTC
UTC in DB confusion when querying in linq from Web API server
我真的需要一些帮助来解决我在根据 SQL 日期字段查询数据时遇到的问题。
我使用以下代码以 UTC 格式存储日期:
objFitCalendarDto.Day = objFitCalendarDto.Day.ToUniversalTime();
该行将日期分配给通过 Entity Framework 插入数据库的模型。
现在,我的查询应该根据日期检索行。所以,我应该能够得到今天、明天、昨天等等的行。
为此,我使用方法在两个日期、开始日期和结束日期之间进行搜索,如下所示:
DateTime dayBegin = DateTime.Today.Date.AddDays(dayOffset);
DateTime dayEnd = DateTime.Today.Date.AddDays(dayOffset + 1);
dayOffset的作用是指定哪一天。如果 Offset 为 0,则我正在搜索 Today。如果 dayOffset 为 1,则我正在搜索具有明天日期的行。
现在,由于我最初以 UTC 格式存储数据,因此我假设我也必须以 UTC 格式搜索它。因此,在执行我的查询之前,我将日期转换为 UTC,如下所示:
dayBegin = TimeZoneInfo.ConvertTimeToUtc(dayBegin);
dayEnd = TimeZoneInfo.ConvertTimeToUtc(dayEnd);
然后我像这样执行查询:
var query = (from f in Db.FitCalendars
where f.FitProgramId == programId &&
f.DayAsDate >= dayBegin && f.DayAsDate < dayEnd
select f);
问题是,它不起作用。当我在 SQL 管理器中查看日期时,我有一行日期为“2016-01-26”。但是,它仅 returns 来自昨天日期的查询。顺便说一句,今天是 2016-01-26。显然我没有得到这个 UTC 概念。谁能看到我在这里做错了什么?我假设如果我将所有内容都存储为 UTC,然后在查询之前将我的查询日期转换为 UTC,那么一切都应该有效。
更新
让我们这样试试:
只要您只存储日期部分(SQL 'date' 类型),您
也只需要比较日期。
而不是
DateTime dayBegin = DateTime.Today.Date.AddDays(dayOffset);
dayBegin = TimeZoneInfo.ConvertTimeToUtc(dayBegin);
我们就这样吧
DateTime dayBegin = DateTime.UtcNow.Date.AddDays(dayOffset);
在这种情况下,dayBegin 无论如何都会是日期(时间是 12:00:00 AM)。这意味着,我们需要用 DbFunctions 截断它。我们需要平等检查这里。
var query = (from f in Db.FitCalendars
where f.FitProgramId == programId &&
f.DayAsDate == DbFunctions.TruncateTime(dayBegin)
select f);
更新结束
我认为问题在于您将日期与时间进行了比较。据我了解,在您的情况下,您只需要比较日期。作为解决方案 - 使用 DbFunctions TruncateTime 函数。它可以在 linq 查询中使用 - 就像在您的代码中一样。
https://msdn.microsoft.com/en-us/library/system.data.entity.dbfunctions.truncatetime(v=vs.113).aspx
所以,完整的解决方案是
var query = (from f in Db.FitCalendars
where f.FitProgramId == programId &&
DbFunctions.TruncateTime(f.DayAsDate) >= DbFunctions.TruncateTime(dayBegin) && DbFunctions.TruncateTime(f.DayAsDate) < DbFunctions.TruncateTime(dayEnd)
select f);
我真的需要一些帮助来解决我在根据 SQL 日期字段查询数据时遇到的问题。
我使用以下代码以 UTC 格式存储日期:
objFitCalendarDto.Day = objFitCalendarDto.Day.ToUniversalTime();
该行将日期分配给通过 Entity Framework 插入数据库的模型。
现在,我的查询应该根据日期检索行。所以,我应该能够得到今天、明天、昨天等等的行。
为此,我使用方法在两个日期、开始日期和结束日期之间进行搜索,如下所示:
DateTime dayBegin = DateTime.Today.Date.AddDays(dayOffset);
DateTime dayEnd = DateTime.Today.Date.AddDays(dayOffset + 1);
dayOffset的作用是指定哪一天。如果 Offset 为 0,则我正在搜索 Today。如果 dayOffset 为 1,则我正在搜索具有明天日期的行。
现在,由于我最初以 UTC 格式存储数据,因此我假设我也必须以 UTC 格式搜索它。因此,在执行我的查询之前,我将日期转换为 UTC,如下所示:
dayBegin = TimeZoneInfo.ConvertTimeToUtc(dayBegin);
dayEnd = TimeZoneInfo.ConvertTimeToUtc(dayEnd);
然后我像这样执行查询:
var query = (from f in Db.FitCalendars
where f.FitProgramId == programId &&
f.DayAsDate >= dayBegin && f.DayAsDate < dayEnd
select f);
问题是,它不起作用。当我在 SQL 管理器中查看日期时,我有一行日期为“2016-01-26”。但是,它仅 returns 来自昨天日期的查询。顺便说一句,今天是 2016-01-26。显然我没有得到这个 UTC 概念。谁能看到我在这里做错了什么?我假设如果我将所有内容都存储为 UTC,然后在查询之前将我的查询日期转换为 UTC,那么一切都应该有效。
更新 让我们这样试试:
只要您只存储日期部分(SQL 'date' 类型),您 也只需要比较日期。
而不是
DateTime dayBegin = DateTime.Today.Date.AddDays(dayOffset); dayBegin = TimeZoneInfo.ConvertTimeToUtc(dayBegin);
我们就这样吧
DateTime dayBegin = DateTime.UtcNow.Date.AddDays(dayOffset);
在这种情况下,dayBegin 无论如何都会是日期(时间是 12:00:00 AM)。这意味着,我们需要用 DbFunctions 截断它。我们需要平等检查这里。
var query = (from f in Db.FitCalendars
where f.FitProgramId == programId &&
f.DayAsDate == DbFunctions.TruncateTime(dayBegin)
select f);
更新结束
我认为问题在于您将日期与时间进行了比较。据我了解,在您的情况下,您只需要比较日期。作为解决方案 - 使用 DbFunctions TruncateTime 函数。它可以在 linq 查询中使用 - 就像在您的代码中一样。
https://msdn.microsoft.com/en-us/library/system.data.entity.dbfunctions.truncatetime(v=vs.113).aspx
所以,完整的解决方案是
var query = (from f in Db.FitCalendars
where f.FitProgramId == programId &&
DbFunctions.TruncateTime(f.DayAsDate) >= DbFunctions.TruncateTime(dayBegin) && DbFunctions.TruncateTime(f.DayAsDate) < DbFunctions.TruncateTime(dayEnd)
select f);