【问题标题】:Which SQL Server sql data type to use in order to preserve UTC date time使用哪种 SQL Server sql 数据类型来保留 UTC 日期时间
【发布时间】:2011-05-27 04:31:55
【问题描述】:

我有一个 SQL Server DB 表,其中有一列“ReceivedDate”定义为“datetime”,其中应包含 UTC 日期...在我的 C# 代码中,我使用实体框架将表映射到一个类,该类具有相应的System.DateTime 类型的属性“ReceivedDate”。

程序将 XML 文件中的日期加载到 DB 中,稍后会检查 XML 中的数据是否与 DB 中的数据相同...当 XML 和 DB 中的 ReceivedDate 日期不匹配时,检查失败。 ..例如:

ReceivedDate from XML:
<ReceivedDate>2010-12-16T22:53:27.5912217Z</ReceivedDate>

ReceivedDate from DB:
2010-12-16 22:53:27.590

经过一些调试,我注意到 DB 中的日期没有将 Kind 属性设置为 Utc,并且刻度数要少得多,因此日期比较失败...

  • 如何在 SQL 中存储完整的 UTC 日期 服务器所以当实体框架 检索它,我得到 System.DateTime 与那个完全相同的值 来自 XML 文件(包括 Kind=Utc)?
  • 这只是使用的问题吗 我的列的不同 sql 数据类型 (例如 datetime2 而不是 datetime)?

更新:

我解决这个问题的方法是:

  1. 将 sql 数据类型更改为“datetime2”以匹配 sql 数据类型和 .net System.DateTime 之间的精度
  2. 在我的 POCO 中,我覆盖了 Equals,在检查 ReceivedDate 属性时,我刚刚从 ReceivedDate 创建了另一个 DateTime 变量,但使用了 Kind == Utc 的构造函数。

这可行,尽管我同意使用 DateTimeOffset 可能是更好的解决方案。

【问题讨论】:

    标签: c# sql-server datetime entity-framework-4 utc


    【解决方案1】:

    使用datetimeoffset 存储在 SQL Server 上。

    定义一个日期,该日期与一天中具有时区意识且基于 24 小时制的时间相结合。

    另外,请考虑在您的 .NET 代码中使用 DateTimeOffset 结构而不是 DateTime

    【讨论】:

    • 不幸的是,这对我来说不是一个选项......域模型属性设置为 System.DateTime,如果我使用“datetimeoffset”,正如你所指出的,我将不得不使用 System.DateTimeOffest ...我需要一个解决方案来使用 DateTime 保留 UTC(如果可能的话)
    • 看来DateTimeOffset 结构只有在你 偏移量时才有用:即你使用SQL 的DateTimeOffset 或者你知道UTC 日期时间并且 时区。但是 +1 对于开发/改造新东西的人们来说是一个真正可行的选择。
    • @zam6ak,那么你的域模型是错误的。 EF 4 支持DateTimeOffset。更新您的模型。
    • @Craig Stuntz 有时,在现实生活中,您只是无法更改域模型(在我的例子中,域模型已在几年前建立)...
    • @zam6ak:那么你不需要(EF)直接映射到它。您可以映射到正确的类型并投影到对象空间中的域模型上。
    【解决方案2】:

    Sql server中的datetime只有an accuracy of one three-hundredth of a second

    .Net 中的准确率更高。因此,DB 数据是四舍五入的,而不是相同的。如果你看你的数据,误差是 0.0012217 秒。

    如果可能,您可以使用datetime2:

    0 到 7 位,精度为 100ns。默认精度为 7 位。

    datetime2 使用与 .Net DateTime 相同的准确度。

    【讨论】:

    • 正如我所怀疑的(在我的问题中),精度是问题的一部分......更改为“datetime2”有帮助,但是实体框架仍然没有将 Kind 属性设置为“Utc”(根据到这个帖子:social.msdn.microsoft.com/Forums/en/adodotnetentityframework/…)
    • 感谢您的澄清。我将您的回复设置为答案,因为它更符合我的用例。但是,如果我可以选择更改我的域模型,我会选择 @Oded 答案,因为 DateTimeOffset 可能是更优雅的解决方案。
    【解决方案3】:

    如果您想将数据库 UTC DateTimes 转换为 C# DateTimes,请执行此操作。创建DateTime 时,使用带有DateTimeKind 参数的构造函数:

    DateTime utcDateTime = new DateTime(((DateTime)row["myUtcDateTime"]).Ticks, DateTimeKind.Utc)
    

    如果您正在寻找一种更好的方式在 SQL 中实际存储它(并且您在 2008 年),请遵循 @Oded 的建议。

    【讨论】:

    • 正如我在问题中提到的,我使用的是实体框架,所以我的域模型由 EF “管理” - 我不是自己“加载”日期...
    • @zam,啊......好吧.....实体框架比切片面包更好!
    • @zam6ak, @Brad:如果你坚持使用错误的数据类型——EF 和 SQL Server 都支持DateTimeOffset,如果你打算这样做,你应该使用混合异构时区——您仍然可以使用 EF 投影编写等效代码。但是如果你希望它是自动的,那么你必须使用正确的类型。
    • @Craig,我绝对同意在两种情况下(SQL 和 .NET)使用DateTimeOffset 是最好的方法。
    • @Craig Stuntz 我也同意你的观点,但正如我提到的,我的域模型是“一成不变的”(POCO 的集合),我无法更改它,所以我必须使用 DateTime。
    猜你喜欢
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2010-10-10
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 2012-09-20
    相关资源
    最近更新 更多