【问题标题】:LINQ query maps dates incorrectlyLINQ 查询映射日期不正确
【发布时间】:2018-04-04 22:43:04
【问题描述】:

我的查询如下所示:

using (var ctx = new PCLvsCompContext())
{
    var brokerId = broker?.Id;
    var symbolId = company?.Id;

    var result = (from t in ctx.TradeHistoryJoineds
            where t.TradeDate >= fromDate
                && t.TradeDate <= toDate
                && (brokerId == null || t.BrokerId == brokerId)
                && (symbolId == null || t.SymbolId == symbolId)
            select t).OrderBy(x => x.TradeDate).ThenBy(x => x.BrokerName).ToList();

    return result;
}

例如,我使用 fromDate March-01-2017 toDate March-31-2017 这样的日期运行此查询。然后,我在此查询生成的 SQL 分析器中捕获了生成的 sql,并在 SQL 管理工作室中运行它。输出与预期的一样,每个工作日,每家公司都有一些交易。该查询基于将所有日期转换为“日期时间”的视图,以便 excel 可以正确地将它们解析为日期。但是,当我在“返回结果”处设置断点并检查日期时,除 2 个日期外,所有日期均为 2017 年 3 月 1 日。这是不正确的,SQL 管理器中的查询结果显示了 3 月几乎每个工作日的交易(这是正确的)。

这里发生了什么?为什么 Linq 会失去理智?

【问题讨论】:

  • SQL 管理器中的查询和 linq 中的查询是否返回相同数量的结果?
  • 你提到了 Excel,但你也提到了 SSMS;这里的后端是什么?您是否检查过您正在连接的地方认为您正在连接?除了一些非常特殊的例外,查询通常通过 ADO.NET 和 SSMS 做同样的事情。另外,你确定你不只是看第一场比赛吗?例如,我们会期望 March-1st 记录排在第一位(因为OrderBy
  • toDate的值是多少?
  • 会不会 TradeDate 是 UTC 但 fromDate, toDate 是本地时间?您是否依赖从字符串到日期时间的转换?与您的操作系统相比,数据库的语言是什么?

标签: c# linq


【解决方案1】:

虽然根据结果我无法确切地看到您最终会如何得到这些结果,但您可能正在处理DateTime 时区问题是很常见的。我怀疑您可能使用来自DateTime.NowDateTime 对象而不是DateTime.UtcNow 将日期保存到数据库中。因此,在那个时间点,基于调用它的机器,它将基于该机器的时区和日期光节约。

不应使用DateTime 对象,因为它可能与 SQL 数据库的区域、进行此 LINQ 调用的服务器的区域相关,因此这两个区域可能位于不同的时区。

您应该始终使用DateTimeOffset

如果由于某种原因您不能这样做,请仔细检查您的日期 toDate 和 fromDate 并执行以下操作:

var utcToDate = toDate.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

var utcFromDate = toDate.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

如果它在 2018 年 4 月 3 日 22:56 运行,会给出类似的结果。

2018-04-03T22:56:57.740Z

您还需要确保在将任何日期保存到 SQL 后备存储时首先执行 ToUniversalTime()。你可以直接用普通的SQL查询来检查你的SQL表,它们应该以与上面相同的UTC字符串格式存储在数据库中,然后比较是否有效。

但是,我强烈建议您更改所有 DateTime 调用并转到 DateTimeOffset。在大多数情况下,唯一使用DateTime 的时间是为了最终显示给用户。

【讨论】:

  • 感谢您的精彩总结。目前我工作的公司中的所有数据库都直接使用日期,所以我会研究一下迁移到偏移量会有多难。
【解决方案2】:

感谢大家的建议。对于那些熟悉 linq、EF 和视图的人来说,这似乎是一个愚蠢的疏忽,但我会为其他人发布我的耻辱,以防万一他们发生这种情况,因为原因和结果行为并没有立即明显联系起来(可以看出所有的建议都没有真正指向答案)。

当您使用 linq 和 Entity Framework 查询视图时,您显然必须有一个名为“Id”的列,否则 Entity Framework 无法将任何行彼此区分开来,而只是进行某种我可以的重复' 不太清楚(即使没有 Id 列,所有行都基于它们的数据是唯一的,所以我不太明白为什么这是必要的)。

因此,通过向视图添加带有“Id”别名的 TradeId,Entity Framework 似乎恢复了理智并按预期映射数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-17
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    • 2019-09-02
    相关资源
    最近更新 更多