【问题标题】:Loss of precision when mapping datatable columns to datetime2 fields将数据表列映射到 datetime2 字段时丢失精度
【发布时间】:2016-12-07 10:43:54
【问题描述】:

背景

字段 TimestampCreation 是在数据库中这样创建的:

[TimestampCreation] [datetime2](7) NOT NULL

如果我将字段添加到这样的数据表中:

table.Columns.Add(new DataColumn("TimestampCreation", typeof(DateTime)));

该值会丢失精度,因为它的存储方式如下:

2016-12-07 11:38:39.4990000

应该是什么时候

2016-12-07 11:38:39.4998426

我尝试过的一种解决方案

如果我像这样添加列:

table.Columns.Add(new DataColumn("TimestampCreation", typeof(string))); // Actually datetime2

该值已正确存储到 DB,但这感觉很脏/hacky。

在代码中的使用

值是这样设置的:

public static void AddToTable(this EntityDto source, DataTable table)
{
    var row = table.NewRow();

    ...
    ...
    row["TimestampLastModification"] = source.TimestampLastModification;

    table.Rows.Add(row);
}

其中source.TimestampLastModification 的类型为DateTime

public DateTime TimestampLastModification { get; set; }

接下来将数据表保存到存储中,如下所示:

Root.PluginManager().PersistentStorage(ParametersHelper.OverallSchema).Insert(ref table)

问题

datetime2 字段添加到数据列并保持预期精度的正确方法是什么?

【问题讨论】:

  • 将数据从DataTable 传输到数据库的代码在哪里?这就是事情变得一团糟的地方,DATETIME 被用作类型而不是DATETIME2System.DateTime 本身具有足够的精度,DataColumn 只是按原样存储值。
  • 好的,我会更新的。
  • 这仍然缺少 写入 到数据库(或将其读入 EntityDto,具体取决于您的方案)的代码。 table 只是内存中的表示,不是你的问题。
  • @JeroenMostert:这是一个,我也添加了插入代码。它是适用于数据集/数据表的旧提供程序。
  • 你有它。无论Root.PluginManager().PersistentStorage().Insert() 的实现是什么,决定所有DateTime 列都应该作为DATETIME 而不是DATETIME2 传输。如果你不能影响它,那你就不走运了。 DataColumn 无法明确地传达特定于提供程序的类型,例如 DATETIME2(即使这样做,您的提供程序也可能不支持)。您可以尝试传入DateTimeOffset,但我怀疑它对此是否有支持。如果您必须传递一个字符串,请确保它是 ISO (.ToString("yyyyMMdd HH:mm:ss.fffffff"))。

标签: .net sql-server precision datetime2


【解决方案1】:

我找到了解决方案,这是我自己的事情,而不是第三方依赖项。我通过在查询中将日期转换为 nvarchar 来修复它:

SELECT CONVERT(VARCHAR, [TimestampLastModification], 126) [TimestampLastModification]
FROM ...

接下来我通过代码将字符串转换为日期时间:

this.TimestampLastModification = Convert.ToDateTime(source["TimestampLastModification"].ToString()),

奇怪的是,将一个实际上是 DateTime 类型的对象转换为 DateTime 会导致精度损失,但上述方法确实有效。

【讨论】:

  • 您在这里所做的是将 T-SQL 类型 DATETIME2 转换为字符串,然后将其转换为 .NET System.DateTime。这行得通。没有工作的是将 T-SQL 类型 DATETIME2 读取为 DATETIME 类型(这是您的提供者正在做的事情)。 DATETIME != System.DateTime。精度损失是由 DATETIME T-SQL 类型一开始就具有糟糕的精度引起的,而不是因为您正在转换对象。另一方面,DATETIME2 是专门为与System.DateTime 保持一致而创建的(但需要支持,因为它不是标准类型)。
猜你喜欢
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 2016-10-26
  • 2019-02-22
  • 2020-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多