2013-08-30 12 views
6

jak czytamy wartości zerowe całkowitą od danych SQL Readerdopuszczające wartość null wartości całkowite z czytnikiem

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 cant czytać z czytnikiem

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

Co to jest 'mb.Mem_ResPin' zadeklarowane jako? – ChrisF

+2

Wiem, że już rozmawialiśmy o tym, ale "dapper" po prostu * wykonałby tę pracę * bez ciebie, waląc głową w ADO.NET na każdym kroku ... po prostu mówisz - jest powód, dla którego to napisaliśmy. ..Aby uniknąć * dokładnie * tego rodzaju bólu –

+0

@Marc, i mogę ** w pełni ** potwierdzić, dlaczego Dapper jest ** najlepszym ** ORMem na rynku! I to nic nie kosztuje! –

Odpowiedz

8

Wystarczy przekształcić go, jak to zrobić w poprzednim rzędzie

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

pokazuje eror "Obiekt nie może być rzutowany z DBNull na inne typy." – neel

+0

zobacz moją odpowiedź na leczenie DBNull –

1

Porównać z DBNull.

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

pokazuje błąd nie można niejawnie przekonwertować typu int? do int – neel

+0

Czy jesteś pewien, że 'mb.Mem_ResPin' jest typem' int? '? – keyboardP

2

Istnieje kilka podejść tutaj. Niestety, DBNull sprawia, że ​​to irytujące - reader[name] API zwraca object, który może być wartością, lub może być DBNull.Value - więc trzeba to sprawdzić (is) i obsługiwać go. Innym podejściem jest użycie API reader.IsDBNull(ordinal), ale jak zauważysz: to wymaga porządkowej (indeks kolumny), a nie nazwa. W obu przypadkach, można dodać takie rzeczy jak metod użytkowych pomóc:

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

następnie (na przykład):

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

jednak ponownie: narzędzia, takie jak „elegancki” może zrobić to dużo łatwiej ty; pojedynczy Query<T>(tsql, args).SingleOrDefault() zajmowałby się wszystkim tym, w tym zerami, Nullable<T> i szeregiem innych scenariuszy.

+0

Ten kod spowodowałby błąd rzutowania podczas przesyłania do (int?). Najpierw musisz rozpakować do zwykłego int. –

+0

@MennovandenHeuvel nie, nie. Spróbuj. Co gorsza: rozpakowanie do 'int' (a nie' int? ') Sprawiłoby, że wyrzuciłoby' NullReferenceException' za każdym razem, gdy wartość wynosi 'null' (co jest tu jawnie oczekiwanym scenariuszem) –

3

Napisz proste opakowanie np. jako metodę rozszerzenia i sprawdzić IsDBNull wewnątrz:

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

Wykorzystanie:

var result = reader.SafeGetInt(colName); 
1

używam rodzajowe metodę rozszerzenia dla wszystkich DB rzuca:

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; 
    } 

próbuje traktować każdą sytuację i napotkane w naszym kodzie. Dostosuj warunki w zależności od sytuacji.

Zastosowanie:

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

Może spróbuj tego przedłużeniu:

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; 
    } 
} 

i używać tak:

 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

Można użyć SqlDataReader.GetSqlInt32 obsłużyć Nullable<int>:

SqlInt32 resPin = reader.GetSqlInt32(reader.GetOrdinal("Mem_ResPin")); 
mb.Mem_ResPin = resPin.IsNull ? (int?) null : resPin.Value; 
Powiązane problemy