375 Stimmen

SQL Data Reader - Behandlung von Null-Spaltenwerten

Ich verwende einen SQLdatareader, um POCOs aus einer Datenbank zu erstellen. Der Code funktioniert, außer wenn er auf einen Nullwert in der Datenbank trifft. Wenn zum Beispiel die Spalte Vorname in der Datenbank einen Nullwert enthält, wird eine Ausnahme ausgelöst.

employee.FirstName = sqlreader.GetString(indexFirstName);

Wie kann man in dieser Situation am besten mit Nullwerten umgehen?

596voto

marc_s Punkte 701497

Sie müssen prüfen, ob IsDBNull :

if(!SqlReader.IsDBNull(indexFirstName))
{
  employee.FirstName = sqlreader.GetString(indexFirstName);
}

Das ist die einzige zuverlässige Möglichkeit, diese Situation zu erkennen und zu bewältigen.

Ich habe diese Dinge in Erweiterungsmethoden verpackt und tendiere dazu, einen Standardwert zurückzugeben, wenn die Spalte tatsächlich null :

public static string SafeGetString(this SqlDataReader reader, int colIndex)
{
   if(!reader.IsDBNull(colIndex))
       return reader.GetString(colIndex);
   return string.Empty;
}

Jetzt kann man es so nennen:

employee.FirstName = SqlReader.SafeGetString(indexFirstName);

und Sie müssen sich nie um eine Ausnahme oder eine null Wert wieder.

246voto

stevehipwell Punkte 52558

Sie sollten die as Operator in Kombination mit dem ?? Operator für Standardwerte. Werttypen müssen als nullable gelesen werden und einen Standardwert erhalten.

employee.FirstName = sqlreader[indexFirstName] as string;
employee.Age = sqlreader[indexAge] as int? ?? default(int);

En as Operator übernimmt das Casting einschließlich der Prüfung auf DBNull.

38voto

Gone Coding Punkte 90304
employee.FirstName = sqlreader[indexFirstName] as string;

Für Ganzzahlen können Sie GetValueOrDefault() verwenden, wenn Sie in einen nullbaren int umwandeln.

employee.Age = (sqlreader[indexAge] as int?).GetValueOrDefault();

oder der Null-Koaleszenz-Operator ( ?? ).

employee.Age = (sqlreader[indexAge] as int?) ?? 0;

28voto

ZXX Punkte 4586

IsDbNull(int) ist in der Regel viel langsamer als die Verwendung von Methoden wie GetSqlDateTime und vergleicht dann mit DBNull.Value . Versuchen Sie diese Erweiterungsmethoden für SqlDataReader .

public static T Def<T>(this SqlDataReader r, int ord)
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return default(T);
    return ((INullable)t).IsNull ? default(T) : (T)t;
}

public static T? Val<T>(this SqlDataReader r, int ord) where T:struct
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? (T?)null : (T)t;
}

public static T Ref<T>(this SqlDataReader r, int ord) where T : class
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? null : (T)t;
}

Verwenden Sie sie so:

var dd = r.Val<DateTime>(ords[4]);
var ii = r.Def<int>(ords[0]);
int nn = r.Def<int>(ords[0]);

26voto

PJ3 Punkte 3118

reader.IsDbNull(ColumnIndex) funktioniert, wie viele Antworten besagen.

Und ich möchte erwähnen, dass es bei der Arbeit mit Spaltennamen bequemer sein kann, einfach Typen zu vergleichen.

if(reader["TeacherImage"].GetType() == typeof(DBNull)) { //logic }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X