2011-11-03 2 views
8
int topID = 0; 
string TopIDQuery = "Select TopID from tbl_Organisation where [email protected]"; 

paramet[0] = new MySqlParameter("@OrgID", MySqlDbType.Int32); 
paramet[0].Value = OrgID; 

reader = server.ExecuteReader(CommandType.Text, TopIDQuery, paramet); 

while (reader.Read()) 
{ 
    topID = Convert.ToInt32(reader["TopID"]); 
} 

reader.Close(); 

Czytam topID z tabeli, gdy TopID jest null Chcę zostawić topID jako 0, ale ponieważ jest zerowy jest rzucanie błąd, jak mogę obsłużyć ten błąd, gdy topID jest nullObiekt nie może być rzutowany z DBNull na inne typy. Błąd gdy wartość null jest odczytywany przez czytnik

Odpowiedz

6

Zmień swój kod czytanie:

while (reader.Read()) 
{ 
    if(reader.IsDBNull(reader.GetOrdinal("TopID"))) 
     topID = 0; 
    else 
     topID = Convert.ToInt32(reader["TopID"]); 
} 
+0

CS1502: Najlepiej przeciążona metoda dopasowania dla "System.Data.Common.DbDataReader.IsDBNull (int)" ma pewne nieprawidłowe argumenty ten sam błąd – Mark

+0

@ Mark: oops, przepraszam - zaktualizował moją odpowiedź –

4

połączeń IsDBNull() na czytelnika sprawdzić kolumnę przed przystąpieniem do konwertowania go:

using (reader = server.ExecuteReader(CommandType.Text, TopIDQuery, paramet)) 
    { 
     while (reader.Read()) 
     { 
      var column = reader.GetOrdinal("TopID"); 

      if (!reader.IsDBNull(column)) 
       topID = Convert.ToInt32(reader[column]); 
      } 
     } 
    } 

Albo porównać przeciwko DBNull.Value:

var value = reader["TopID"]; 

    if (value != DBNull.Value) 
    { 
     topID = Convert.ToInt32(value); 
    } 
+0

Najlepsza przeciążona metoda pasująca do 'System.Data.Common.DbDataReader.IsDBNull (int)' ma kilka nieprawidłowych argumentów błąd, jak go rozwiązać – Mark

+0

Niestety, wymaga to identyfikatora kolumny, zapomniałem o tym :-) Aktualizacja, ... –

1

użyć testu:

int columnNr = reader.GetOrdinal("TopID"); 
if (!reader.IsDBNull(columnNr)) { 
    topID = reader.GetInt32(columnNr); 
} 
+0

Jeśli określisz numer kolumny raz przed w pętli, kod będzie trochę szybszy. –

1

Problemem jest to, że starają się ustawić int o wartości null, a nie w odczycie. można to zrobić, aby ustawić wartość alternatywnego jeśli jeden próbujesz wprowadzić jest zerowy:

topID = Convert.ToInt32(reader["TopID"]) ?? 0; 

Inną alternatywą jest to, że można użyć zerowalne liczb całkowitych przez inicjowanie topID tak:

int? topID = 0 

ale zrobienie tego nadal będzie wymagało sprawdzenia null gdziekolwiek indziej, wraz z innymi rzeczami, które trzeba obsłużyć, więc poleciłbym użycie podwójnego znaku zapytania na twoim zestawie wartości, jak pokazałem pierwszy.

+0

Operator "??" nie może być zastosowany do operandów typu 'int' i 'int' –

+0

Poprawnie, ale może być użyty, gdy czytnik ["TopId"] jest w stanie zwrócić wartość zerową, ponieważ zamiast rzucać referencję zerową, Convert.ToInt32 zapewni null output, który jest nieprawidłowy na topID, który ustawił. – Nikkoli

0

Musisz sprawdzić, czy wartość ma wartość DBNull, zanim spróbujesz ją odzyskać. Zaleca się także używanie GetInt32() przez Convert.ToInt32(), ponieważ stwierdzono, że wewnętrzna optymalizacja GetInt32() może ulec zmianie tam, gdzie będzie to szybsze niż użycie Convert.ToInt32(). Dowiedziałem się o tym dawno temu i nie mam dla ciebie artykułu referencyjnego. W tym czasie dowiedziałem się tego GetInt32() została wewnętrznie za pomocą Convert.ToInt32()

while(reader.Read()) { 
    int TopIDIndex = reader.GetOrdinal("TopID"); 
    topID = reader.IsDBNull(TopIDIndex) 
     ? 0 
     : reader.GetInt32(TopIDIndex); 
} 
0

Lubię używać DataTable zamiast DataReader. Nienawidzę powtarzalne boilerplate, więc dodałem kilka metod rozszerzenie do do klasy DataRow do hermetyzacji przybitej logiki i uczynić dla kodu bardziej czytelny:

DataTable dt = ExecStoredProcedure() ; 
foreach (DataRow dr in dt) 
{ 
    int  id   = dr.CastAsInt("id") ; 
    dateTime? dtLastUpdated = dr.CastAsDateTimeNullable("last_update_date") ; 
    int?  col3   = dr.CastASIntNullable(3) ; 
} 

tu kod na rzutowanie w dół wartość kolumny z DataRow do int/int?:

#region downcast to int 

public static int CastAsInt(this DataRow row , int index) 
{ 
    return toInt(row[index]) ; 
} 
public static int CastAsInt(this DataRow row , string columnName) 
{ 
    return toInt(row[columnName]) ; 
} 

public static int? CastAsIntNullable(this DataRow row , int index) 
{ 
    return toIntNullable(row[index]); 
} 
public static int? CastAsIntNullable(this DataRow row , string columnName) 
{ 
    return toIntNullable(row[columnName]) ; 
} 

#region conversion helpers 

private static int toInt(object o) 
{ 
    int value = (int)o; 
    return value; 
} 

private static int? toIntNullable(object o) 
{ 
    bool hasValue = !(o is DBNull); 
    int? value = (hasValue ? (int?) o : (int?) null) ; 
    return value; 
} 

#endregion conversion helpers 

#endregion downcast to int 

pewno wisi podobnych metod przedłużających off DataReader byłoby dość proste.

0

Oto kod, w którym AutoGenerate dowolny identyfikator z bazy danych MS Access na stronie obciążenia w jakiejkolwiek formie Rejestracji

void Number() 
{ 
    con.Open(); 
    int id; 
    cmd = new OleDbCommand("select max(ID) from Entry", con); 
    string value = (cmd.ExecuteScalar().ToString()); 
    string max; 
    if (value != null) 
    {  
     max = "0"+value; 
     id = Convert.ToInt32(max); 
     lblNumber.Text = "Acronym of Reg form like for Emp for Employee" 
         + Convert.ToString((id + 1)); 

    } 
    con.Close(); 
} 
0

użyć rodzajowe metodę rozszerzenia na czytniku (patrz podobny SO question)

topID = reader.GetFieldValueOrDefaultIfDBNull<Int32>("TopID"); 

Wdrożenie tej metody rozszerzenie na klasę czytnika (MySQL, SQL, Oracle, itd.)

public static T GetFieldValueOrDefaultIfDBNull<T>(this SqlDataReader reader, string indexName) 
{ 
    if (reader.IsDBNull(reader.GetOrdinal(indexName))) 
    { 
     return default(T); // returns the default value for the type 
    } 
    else 
    { 
     return reader.GetFieldValue<T>(reader.GetOrdinal(indexName)); 
    } 
}