2013-08-30 2 views
6

, как мы читаем число нулевых значений из Sql чтения данныхОбнуляемые целые значения от читателя

SqlDataReader reader = cmd.ExecuteReader(); 
if (reader.Read() == true) 
{ 
    mb.Id = (int)reader["Id"]; 
    mb.Mem_NA = (string)reader["Mem_NA"]; 
    mb.Mem_ResAdd4 = reader["Mem_ResAdd4"] == System.DBNull.Value ? null : (string)reader["Mem_ResAdd4"]; 
    // 
    mb.Mem_ResPin = reader["Mem_ResPin"] as int? ?? default(int); 
    // shows the error "Object cannot be cast from DBNull to other types." 
} 

mb.Mem_ResPin косяк читать читателя

CREATE TABLE [dbo].[Mem_Basic] (
[Id]   INT   IDENTITY (1, 1) NOT NULL, 
[Mem_NA]  VARCHAR (100) NOT NULL, 
[Mem_ResAdd4] VARCHAR (100) NULL, 
[Mem_ResPin] INT   NULL, 
PRIMARY KEY CLUSTERED ([Id] ASC) 
); 
+0

Что такое 'mb.Mem_ResPin', объявленный как? – ChrisF

+2

Я знаю, что у нас уже был этот разговор, но «dapper» просто сделал бы эту работу *, если бы вы не стучали головой о ADO.NET на каждом шагу пути ... просто скажите, - есть причина, по которой мы его написали. ..чтобы избежать * точно * такого рода боли –

+0

@Marc, и я могу ** полностью ** подтвердить, почему Dapper является ** лучшим ** ORM на рынке сегодня! И это бесплатно не меньше! –

ответ

8

Просто преобразовать его, как вы делаете в предыдущей строке

mb.Mem_ResAdd4 = reader["Mem_ResAdd4"] == System.DBNull.Value ? null : (string)reader["Mem_ResAdd4"]; 
// 
    mb.Mem_ResPin = reader["Mem_ResPin"]== System.DBNull.Value ? default(int):(int)reader["Mem_ResPin"] 
+0

показывает eror «Объект нельзя отбрасывать из DBNull в другие типы». – neel

+0

см. Мой ответ для лечения DBNull –

1

Сравнение против DBNull.

var resPin = reader["Mem_ResPin"]; 
if(!Convert.IsDBNull(resPin)) 
    mb.Mem_ResPin = resPin as int?; 
else 
    mb.Mem_ResPin = new Nullable<int>(); 
+0

показывает ошибку не может неявно преобразовать тип int? to int – neel

+0

Вы уверены, что 'mb.Mem_ResPin' - это тип' int? '? – keyboardP

2

Здесь есть несколько подходов. К сожалению, DBNull делает это досаду - API reader[name] возвращает object, который может быть вашим значением, или это может быть DBNull.Value - так что вы должны проверить это (is) и обработать его. Другой подход заключается в использовании API reader.IsDBNull(ordinal), но, как вы заметите: для этого требуется порядковый номер (индекс столбца), а не имя. В любом случае, вы можете добавить такие вещи, как методы полезности, чтобы помочь:

static object Read(IDataReader reader, string name) 
{ 
    var val = reader[name]; 
    return val is DBNull ? (object)null : val; 
} 

затем (к примеру):

mb.Mem_ResPin = (int?)Read(reader, "Mem_ResPin") 

Однако, опять же: инструменты, такие как «щеголеватый» может сделать это намного проще вы; один Query<T>(tsql, args).SingleOrDefault() будет иметь дело со всем этим, включая нули, Nullable<T> и ряд других сценариев.

+0

Этот код приведет к ошибке при бросании в (int?). Сначала вам нужно отменить ввод в обычный int. –

+0

@MennovandenHeuvel нет, вы этого не делаете. Попробуй. Хуже: unboxing к 'int' (а не' int? ') Фактически заставит его выкинуть« NullReferenceException »всякий раз, когда значение равно« null »(здесь явно показан ожидаемый сценарий) –

3

Напишите простую обертку, например. как метод расширения и проверить IsDBNull внутри:

public static int SafeGetInt(this SqlDataReader reader, string colName) 
{ 
    var colIndex = reader.GetOrdinal(colName); 
    return !reader.IsDBNull(colIndex) ? reader.GetInt32(colIndex) : default(int); 
} 

использование:

var result = reader.SafeGetInt(colName); 
1

Я использую общий метод расширения для всех БД бросает:

public static T? DbCast<T>(this object dbValue) 
     where T : struct 
    { 
     if (dbValue == null) 
     { 
      return null; 
     } 
     if (dbValue is System.DBNull) 
     { 
      return null; 
     } 
     T? value = dbValue as T?; 
     if (value != null) 
     { 
      return value; 
     } 
     var conv = dbValue as IConvertible; 
     if (conv != null) 
     { 
      value = (T)conv.ToType(typeof(T), CultureInfo.InvariantCulture); 
     } 
     return value; 
    } 

пытается рассматривать каждую ситуацию я встречаются в нашем коде. Отрегулируйте условия, необходимые для вашей ситуации.

Использование:

int? value = reader["Mem_ResAdd4"].DbCast<int>() 
2

Может попробовать это расширение,:

public static class Helper 
{ 
    public static T GetSafe<T>(this SqlDataReader reader, string name) 
    { 
     var value = reader[name]; 
     return value == DBNull.Value ? default(T) : (T) value; 
    } 
} 

и использовать так:

 if (reader.Read()) 
     { 
      Mb mb = new Mb(); 
      mb.Id = reader.GetSafe<int>("Id"); 
      mb.Mem_NA = reader.GetSafe<string>("Mem_NA"); 
      mb.Mem_ResAdd4 = reader.GetSafe<string>("Mem_ResAdd4"); 

      mb.Mem_ResPin = reader.GetSafe<int>("ResPin"); 
     } 
1

Вы можете использовать SqlDataReader.GetSqlInt32 обрабатывать Nullable<int>:

SqlInt32 resPin = reader.GetSqlInt32(reader.GetOrdinal("Mem_ResPin")); 
mb.Mem_ResPin = resPin.IsNull ? (int?) null : resPin.Value; 
Смежные вопросы