【问题标题】:DateTime2 to C# DateTime with SqlDataReader使用 SqlDataReader 将 DateTime2 转换为 C# DateTime
【发布时间】:2015-05-01 02:10:38
【问题描述】:

我知道这可能是个骗局,但我花了好几个小时寻找答案,但似乎找不到。

我目前正在创建一个检索音乐会数据的网络 API。

我有一个 SQL Server 表,其中包含开始日期和结束日期,两者都是 datetime2 类型。我以这种格式插入了日期,在查看数据库时它们不会引起任何问题:

2015-10-08T20:00:00.0000000+01:00

我的模特:

public class Concert
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int LocationId { get; set; }

    [Column(TypeName = "DateTime2")]
    public DateTime Start { get; set; }

    [Column(TypeName = "DateTime2")]
    public DateTime End { get; set; }

    public string Description { get; set; }
    public string Url { get; set; }
}

还有我在类中显示我的数据库数据的方法:

    public List<Concert> getAll() 
    {
        List<Concert> concerts = new List<Concert>();

        SqlConnection connection = CasWebAPIdb.getConnection();
        String selectAll = "SELECT ConcertId, ConcertName, ConcertLocationId FROM dbo.Concerts";
        SqlCommand selectCommand = new SqlCommand(selectAll, connection);

        try
        {
            connection.Open();
            SqlDataReader reader = selectCommand.ExecuteReader();
            var isoDateTimeFormat = CultureInfo.InvariantCulture.DateTimeFormat;

            while (reader.Read())
            {
                //Debug.WriteLine("lol: " + reader["ConcertEnd"].GetType());

                Concert concert = new Concert();

                concert.Id = (int)reader["ConcertId"];
                concert.Name = reader["ConcertName"].ToString();
                concert.LocationId = (int)reader["ConcertLocationId"];
                concert.Start = (DateTime)reader["ConcertStart"];
                concert.End = (DateTime)reader["ConcertEnd"];

                concerts.Add(concert);
            }
        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            connection.Close();
        }
        return concerts;
    }
}

调试时出现此错误:

System.Data.dll 中出现“System.IndexOutOfRangeException”类型的异常,但未在用户代码中处理

我尝试了很多东西并遵循了很多示例和代码,但我似乎无法正确转换它。有人有想法吗?

解决方案

我忘记在查询中添加“concertStart”和“concertEnd”。 问题已解决,谢谢!

【问题讨论】:

  • 你试过Convert.ToDateTime(reader["ConcertStart"])而不是强制转换吗?
  • 进行强制转换或转换不会有太大的不同。你还没有具体说明问题是什么?它应该作为 SQL 的 DateTime 和 DateTime2 数据类型映射到 .NET 中的 Datetime
  • 当您说您似乎无法正确转换它时,您是如何确定的?您期望的结果是什么,您会得到什么结果?

标签: c# sql-server datetime sqldatareader datetime2


【解决方案1】:

任何想要将 SQL DateTime2 正确恢复为 DateTime 的人,包括 'Kind=Utc'

(DateTime)reader["ConcertEnd"].ToUniversalTime();

否则 DateTime 可能很难确定日期来自哪个时区

【讨论】:

    【解决方案2】:

    问题在于,在您的选择中,您只返回了所需的 3 列:

     String selectAll = "SELECT ConcertId, ConcertName, ConcertLocationId ...";
    

    而在您的阅读器中,您尝试抓取 5 列:

    concert.Id = (int)reader["ConcertId"];
    concert.Name = reader["ConcertName"].ToString();
    concert.LocationId = (int)reader["ConcertLocationId"];
    concert.Start = (DateTime)reader["ConcertStart"];
    concert.End = (DateTime)reader["ConcertEnd"];
    

    因此IndexOutOfRangeException。要么选择所有列,要么从阅读器中删除无关的列。

    该问题与 Sql DateTime2 与 .Net DateTime 无关 - ADO 可以很好地绑定这些。

    【讨论】:

      【解决方案3】:

      首先,如果你想读取ConcertStartConcertEnd 的值,你必须在你的SELECT!!$ 中包含它们

      string selectAll = @"SELECT ConcertId, ConcertName, ConcertLocationId,
                                  ConcertStart, ConcertEnd     <<--- add these!! 
                           FROM dbo.Concerts";
      

      试试这个:

      while (reader.Read())
      {
          Concert concert = new Concert();
      
          concert.Id = (int)reader["ConcertId"];
          concert.Name = reader["ConcertName"].ToString();
          concert.LocationId = (int)reader["ConcertLocationId"];
          concert.Start = reader.GetFieldValue<DateTime>(reader.GetOrdinal("ConcertStart"));
          concert.End = reader.GetFieldValue<DateTime>(reader.GetOrdinal("ConcertEnd"));
      
          concerts.Add(concert);
      }
      

      完全没有问题使用

      从 SQL Server 数据库中读取 DATETIME2(3)
      reader.GetFieldValue<DateTime>(reader.GetOrdinal("ConcertEnd"));
      

      这对你有用吗?

      【讨论】:

      • 天哪,我真是个白痴。只需将日期添加到查询中即可。你是救生员。
      • @Daemun:有时只需要另一双眼睛 :-)
      • 我们如何只得到这个日期?像删除末尾附加的 12:00:00 吗?
      • 在 .NET 中 - 在 DateTime 数据类型上使用 .Date 属性;在 T-SQL 中 - 使用 CAST(column AS DATE)
      【解决方案4】:

      我会使用我找到的扩展方法 here

      public static DateTime ToDate(this string input, bool throwExceptionIfFailed = false)
      {
          DateTime result;
          var valid = DateTime.TryParse(input, out result);
          if (!valid)
              if (throwExceptionIfFailed)
                  throw new FormatException(string.Format("'{0}' cannot be converted as DateTime", input));
         return result;
      }
      

      像这样转换您的数据:

      concert.Start = reader["ConcertStart"].ToString().ToDate();
      concert.End = reader["ConcertEnd"].ToString().ToDate(true); //throws an exception if it fails
      

      希望这会有所帮助!

      【讨论】:

        猜你喜欢
        • 2012-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-30
        • 2013-06-19
        • 2011-07-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多