在C#中从SQL数据库读取DateTime值时,没有毫秒值

15

我在SQL Server中存储了高精度的日期,例如:

2009-09-15 19:43:43.910

但是,当我将该值转换为DateTime时,得到的DateTime对象的毫秒值为0:

reader["Timestamp"] = 15/09/2009 19:43:43.000

对我来说,将这些DateTime值的精度降低至毫秒非常重要-如何做到最好?

更新: 这是执行转换的代码:

DateTime myDate = (DateTime)reader[Timestamp"];

关于SELECT语句并没有什么特别的,事实上它就是一个SELECT * - 没有任何复杂的类型转换等操作

看起来SqlDataReader返回的DateTime对象没有包含毫秒值


3
你是如何进行转换的?请展示你的代码。 - Bob Kaufman
根据该值对您的重要性,您可能需要不同的存储机制。10^-3秒部分已四舍五入。 - Austin Salonen
嗯,我现在能看到了,但是最接近003、005或007仍然比我在C# DateTime中看到的最接近精度的度数要高得多(即1.000)。 - Justin
如果您尝试使用reader["Timestamp"].ToString()会发生什么? - Jon B
1
我敢打赌20美元,你的毫秒数没有被插入到数据库中。 - Josh Stodola
不,我可以在SQL Server Management Studio中清晰地看到毫秒(我的银行账户细节是...... :-p) - Justin
5个回答

20

我曾经也遇到过这个问题,经过一些阅读之后发现,当你像你所做的那样检索日期时

DateTime myDate = (DateTime)reader["Timestamp"];

SQLDataReader会丢失毫秒。但是,如果您使用SQLDataReader的GetDateTime方法,则返回保留毫秒的DateTime对象:

reader.GetDateTime(reader.GetOrdinal("Timestamp"));

6

它有一点帮助,但是那篇文章解释了DateTime类型比SqlDateTime类型具有更高的精度——这种精度在哪里丢失了呢? - Justin

5

这是因为DateTime的默认格式字符串不包括毫秒。

如果使用自定义格式,则可以看到毫秒值。

例如:

  public class Program
  {
    private static string connString = @"Data Source=(local);Initial Catalog=DBTest;Integrated Security=SSPI;";
    public static void Main(string[] args)
    {
      using (SqlConnection conn = new SqlConnection(connString))
      {
        conn.Open();

        using (SqlCommand cmd = new SqlCommand("SELECT * FROM MilliSeconds"))
        {
          cmd.Connection = conn;

          SqlDataReader reader = cmd.ExecuteReader();
          while(reader.Read())
          {
            DateTime dt = (DateTime)reader["TimeCollected"];
            int milliSeconds = dt.Millisecond;
            Console.WriteLine(dt.ToString("yyyy-MM-dd HH:mm:ss.fff"));
          }
        }
      }

      Console.ReadLine();
    }
  }

从具有以下值的数据库:

1   2009-09-22 18:11:12.057 
2   2009-09-22 18:11:28.587 
3   2009-09-22 18:11:29.820

上面代码的输出结果是:
2009-09-22 18:11:12.057 
2009-09-22 18:11:28.587 
2009-09-22 18:11:29.820

2
抱歉,Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff") 返回的是 19:43:43.000 - 请注意,毫秒值都为 0,而数据库中却是910。 - Justin
1
我不同意你的观点。我已经添加了我示例代码的输出结果。 - Magnus Johansson

0

我曾经遇到同样的问题,通过将C# DateTime持久化为SQL bigint并填充DateTime.Ticks来解决问题。这可以保留完整的DateTime精度,并且可以使用DateTime(long ticks)构造函数反序列化。


-1
这是我尝试解决问题的方法:
  1. 在调试器中逐步执行并查看reader[Timestamp"]的类型和值。如果类型不是SqlDateTime,那会让我感到怀疑--然后我会查看查询以找出为什么该列返回了另一种类型而不是DATETIME(或DATETIME2等)。

  2. 如果该值是SqlDateTime并且包含毫秒,则我会将其转换视为问题的源头。为了验证这一点,我会尝试(在调试器或代码中)使用SqlDataReader.GetDateTime()和SqlDataReader.GetSqlDateTime()来查看是否有任何一个返回正确的结果。这显然似乎不太可能成为问题的源头--转换应该可以正常工作。

  3. 如果#1中的值是SqlDateTime但不包含毫秒,则我会寻找数据库中的上游问题--换句话说,您的查询返回了没有毫秒的内容。当您在Management Studio中执行完全相同的查询时,是否看到毫秒?

我猜这是与查询相关的问题。但我很想了解更多。

读取器的类型["Timestamp"]是System.DateTime - 尝试转换为SqlDateTime失败。 - Justin
查询是一个简单的“SELECT * FROM ...” - 在这种情况下,...非常复杂,但我已经在Sql Server Management Studio中执行了完全相同的查询,并查看了毫秒值。 - Justin
当您使用reader.GetSqlDateTime()时,会得到什么?另外,另一种可能性是(如果您的“…”是一个连接),不同表中有两个具有相同名称但具有不同值的列。通过在查询中用一个列名替换*来进行简单测试。 - Justin Grant
结果证明我的问题确实出在查询上 - 我不得不捕获一个分析器跟踪并执行精确的查询,毫秒值为空。 - Justin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接