DateTime2 в C# DateTime с помощью SqlDataReader


Я понимаю, что это может быть обманом, но я потратил часы на поиски ответа и, кажется, не могу его найти.

В настоящее время я создаю веб-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.IndexOutOfRangeException ' произошло в системе.Данные.dll, но не был обработан в пользовательском коде

Я перепробовал много вещей и следовал многим примерам и кодам, но я, кажется, не могу преобразовать это должным образом. У кого-нибудь есть идея?

Решение

Я забыл добавить "concertStart" и "concertEnd" к моему запросу. Проблема решена, спасибо!

3 3

3 ответа:

Прежде всего, если вы хотите прочитать значение ConcertStart и ConcertEnd, вам придется включить их в свой 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"));

Это работает для вас?

Проблема в том, что при выборе вы возвращаете только 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 против .Чистая DateTime - ADO будет выполнить привязку этих просто отлично.

Я бы сделал это с помощью метода расширения, который я нашел здесь

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

Надеюсь, это поможет!