2013-07-05 3 views
8

Мне почти не хочется задавать этот вопрос, кажется, что его попросили миллионы раз раньше, но даже со мной, исследуя другой вопрос, который я все еще не могу понять, в моем случае.Nullable DateTime с SQLDataReader

Я читал, что DateTime является типом NULL, и я попробовал несколько примеров, но я пытаюсь выяснить, является ли оно NULL в базе данных, с которой работает SQLDATAREADER.

Ошибка

System.Data.SqlTypes.SqlNullValueException: Данные Null. Этот метод или свойство не могут быть вызваны значениями Null.

DetailsClass

private DateTime? startingDate; 

public DateTime? StartingDate 
{ 
    get{ return startingDate; } 
    set{ startingDate = value; } 
} 

// constructor 
Public DetailsClass(DateTime? startingDate) 
{ 
    this.startingDate = startingDate; 
} 

DBClass

using (SqlConnection con = new SqlConnection(connectionString)) 
      using (SqlCommand cmd = con.CreateCommand()) 
      { 

       List<DetailsClass> details = new List<DetailsClass>(); 
       DetailsClass dtl; 
       try 
       { 
        con.Open(); 
        cmd.CommandText = "Stored Procedure Name"; 
        cmd.CommandType = CommandType.StoredProcedure; 
        cmd.Parameters.AddWithValue("@MyParameter", myparameter); 

        using (SqlDataReader reader = cmd.ExecuteReader()) 
        { 
         while (reader.Read()) 
         { 
          dtl = new DetailsClass((
           reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))), 
           reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 
           reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"))); 


          details.Add(dtl); 
         } 
         reader.Close(); 
         return details; 

        } 
       } 
+2

"Я читал, что DateTime является обнуляемым типа" - вы читать неправильно. 'DateTime' не имеет значения NULL,' DateTime? 'Есть. – Corak

+0

Я понимаю, что вы сейчас говорите, я только что оставил вопросительный знак – Jay

ответ

25

Вот вспомогательный метод, чтобы получить значение из считывателя

public static class ReaderExtensions { 

    public static DateTime? GetNullableDateTime(this SqlDataReader reader, string name){ 
     var col = reader.GetOrdinal(name); 
     return reader.IsDBNull(col) ? 
        (DateTime?)null : 
        (DateTime?)reader.GetDateTime(col); 
    } 
} 

Обновленная информация о том, как использовать в ответ на комментарий

using (SqlConnection con = new SqlConnection(connectionString)) 
     using (SqlCommand cmd = con.CreateCommand()) 
     { 

      List<DetailsClass> details = new List<DetailsClass>(); 
      DetailsClass dtl; 
      try 
      { 
       con.Open(); 
       cmd.CommandText = "Stored Procedure Name"; 
       cmd.CommandType = CommandType.StoredProcedure; 
       cmd.Parameters.AddWithValue("@MyParameter", myparameter); 

       using (SqlDataReader reader = cmd.ExecuteReader()) 
       { 
        while (reader.Read()) 
        { 
         dtl = new DetailsClass((
          reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))), 
          reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 
          reader.GetNullableDateTime("STARTINGDATE")); 


         details.Add(dtl); 
        } 
        reader.Close(); 
        return details; 

       } 
      } 

Также обратите внимание, вы используете reader.IsDBNull(1), а затем reader.GetOrdinal.Вероятно, должно быть reader.IsDBNull(reader.GetOrdinal("EMAIL"))

+0

.IsDbNull бросает исключение, говорящее, что System.Data.Sqlclient.Sqldatareader не содержит определения для isdbnull любой идеи – Jay

+0

@Jay Потому что я сделал опечатку, это должно быть 'IsDBNull', теперь ответ исправлен –

+0

Im теряя его can not i пропустил это ... спасибо за вашу помощь еще один вопрос, который у вас есть; закончить утверждение после («STARTINGDATE»); но мне нужно поставить a, поэтому я могу добавить больше столбцов для читателя, и если вы посмотрите на мой код, я не назначаю startdatetime = читателю где-нибудь, как бы реализовать его таким образом. – Jay

4

заменить

DateTime startingDate; 

с

DateTime? startingDate; 

Значок вопроса отмечает его как значение с нулевым значением, и ваш читатель должен иметь возможность устанавливать startdate равным null вместо того, чтобы бросать исключение.

вы можете также проверить наличие нулевых значений в то время как ваш читатель работает и заменить нулевые значения с пустыми строками

while(reader.read()) 
{ 
    //column is an int value of your column. I.e: if the column ist the 8th column, set column to 7 (0-based) 
    StartingDate = (reader.IsDBNull(column)) ? null : reader.GetOrdinal("STARTINGDATE")); 
//instead of null you could also return a specific date like 1.1.1900 or String.Empty 
} 
+0

Я отредактировал свой код на основе вашего предложения, но все равно бросаю ту же ошибку. И я знаю, что это поле вызывает причину ошибки, когда я помещаю значение в базу данных, которую он заполняет. – Jay

+3

Этот код является неправильным: reader.GetOrdinal получает целочисленный индекс именованного поля «STARTINGDATE», так почему вы назначаете его в поле DateTime? – Joe

+0

details.StartingDate = reader.IsDBNull (15)? null: reader.GetDateTime (reader.GetOrdinal ("STARTINGDATE")); Получение неявного преобразования null и system.datetime – Jay

0

Попробуйте это:

Сделать startingDate переменную nullable, как это:

DateTime? startingDate; 

Теперь, когда вы извлекаете значение из объекта SqlDataReader, вам необходимо использовать IsDbNull метод, который будет определять, если значение NULL возвращается из базы данных, например:

if !reader.IsDBNull(reader.GetOrdinal("STARTINGDATE")) 
{ 
    startingDate = reader.GetDateTime(reader.GetOrdinal("STARTINGDATE")); 
} 
else 
{ 
    startingDate = null; 
} 

Примечания: Я не уверен, где вы назначаете startingDate к значению чтения из базы данных, потому что это не показано в опубликованном коде. Вот почему я назначил его прямо в моем примере, но вам, возможно, потребуется настроить размещение логики примера.

+0

Спасибо за ответ, чтобы разместить этот код непосредственно в читателе и что такое MiddleName? – Jay

+0

Я выложу свой код, как именно так вы можете видеть, просто пытался показать, что я сделал некоторую работу, чтобы изолировать то, что моя проблема, поэтому не думаю, что я просто прихожу сюда для раздачи, но я ценю вашу помощь благодаря – Jay

+0

Я отправил свой код не всем, но часть, в которой вы должны нуждаться, я бы подумал, что у меня есть мой класс данных, указанный мной конструктором, а также мой класс DB с кодом снова спасибо – Jay

1

Не могли бы вы рассказать нам, в какой строке возникает ошибка при отладке. Было бы проще.

if (! reader.IsDBNull(reader.GetOrdinal("STARTINGDATE"))) { 
    obj.startingDate = reader.GetDateTime(reader.GetOrdinal("STARTINGDATE")); 
} 

нет необходимости явно присвоить нулевое значение, если это DBNull, потому что это обнуляемым типа поэтому по умолчанию он будет содержать нуль.

Ok, в соответствии с обновленным кодом (обратите внимание на комментарии):

while (reader.Read()) { 
    dtl = new DetailsClass((reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))), 

    // here you are checking null for email 
    reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 

    // here you are not checking null for startingdate ? 
    reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"))); 
    details.Add(dtl); 
} 

Давайте попробуем более многословным образом:

while (reader.Read()) { 

    dtl = new DetailsClass(); 

    dtl.membershipgen = reader.IsDBNull(reader.GetOrdinal("MEMBERSHIPGEN")) ? null : reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN")); 
    dtl.email = reader.IsDBNull(reader.GetOrdinal("EMAIL")) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 
    dtl.startingdate = reader.IsDBNull(reader.GetOrdinal("STARTINGDATE")) ? null : reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"))); 

    details.Add(dtl); 
} 
+0

Это коллекция списков, поэтому, когда я отлаживаю ее, выделяется вся моя коллекция и говорит, что указанная выше ошибка я опубликовал, но после того, как это произошло, когда я положил значение в столбце startdate в базе данных, все работает, поэтому я знаю, что это начальная строка даты в моем sqldatareader – Jay

+0

обновила мой ответ на основе вашего недавнего редактирования – Abhitalks

+0

@ abhitalks вам нужно указать свой null как 'DateTime? ', иначе вы получите исключение исключения из компилятора. –

Смежные вопросы