使用SqlDataReader将DateTime2转换为C# DateTime

8

我知道这可能是一个重复的问题,但我已经花了几个小时搜索答案,似乎找不到。

我正在创建一个检索音乐会数据的Web 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"])而不是强制转换吗? - Ofiris
在这里进行强制转换或转换操作并没有什么大的区别。您没有详细说明问题是什么?SQL的DateTime和DateTime2数据类型应该映射到.NET中的Datetime,所以应该可以正常工作。 - Ahmed ilyas
1
当你说无法正确转换时,你是如何确定的?你期望什么结果,而实际得到了什么结果? - Guffa
4个回答

8

首先,如果您想读取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);
}

我完全没有问题使用 DATETIME2(3) 从 SQL Server 数据库中读取值,

reader.GetFieldValue<DateTime>(reader.GetOrdinal("ConcertEnd"));

这对您有效吗?


1
我的天,我真是个傻瓜。只需要将日期添加到查询中即可。你真是救星。 - Dennie
3
有时候,只需要另一双眼睛就可以解决问题。 - marc_s
我们如何仅获取日期?比如删除末尾附加的12:00:00? - paraJdox1
在.NET中 - 在DateTime数据类型上使用.Date属性; 在T-SQL中 - 使用CAST(column AS DATE) - marc_s

1
问题在于你的选择器只返回了所需列中的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可以很好地绑定它们。

0

我会使用我在这里找到的扩展方法来完成它。

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

希望这能帮到你!


0

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

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

否则,DateTime 可能会难以确定日期来自哪个时区。

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