2013-08-31 4 views
9

Ich möchte Dezimalwerte aus der Datenbank abrufen, und ich möchte wissen, welche die empfohlene Methode zum Überprüfen auf Nullwerte ist.SqlDataReader Die beste Methode zum Überprüfen auf Nullwerte -sqlDataReader.IsDBNull vs DBNull.Value

Ich habe auf MSDN - DBNull.Value Field gesehen, dass diese Prüfung selten verwendet wird.

So ist die reader.IsDBNull die beste/effizienteste Möglichkeit, nach Nullen zu suchen?

Ich habe 2 Beispielmethoden erstellt:

public static decimal? GetNullableDecimal(SqlDataReader reader, string fieldName) 
{ 
    if (reader[fieldName] == DBNull.Value) 
    { 
     return null; 
    } 
    return (decimal)reader[fieldName]; 
} 

public static decimal? GetNullableDecimal_2(SqlDataReader reader, string fieldName) 
{ 
    if (reader.IsDBNull(reader[fieldName])) 
    { 
     return null; 
    } 
    return (decimal)reader[fieldName]; 
} 

Die meiste Zeit die Felder null sein werden.

Vielen Dank im Voraus!

+0

Welche auch immer Sie bevorzugen und am besten lesbar finden. Es ist jedoch erwähnenswert, dass Ihre Beispiele nicht streng äquivalent sind, wenn Sie "reader.GetOrdinal" im zweiten Beispiel verwenden. –

+1

Intern wird die Syntax 'reader [fieldName]' aufgelöst in 'reader.GetOrdinal (fieldName)' – Steve

+0

Ich habe das Beispiel so geändert, dass in beiden Fällen reader [fieldName] – diver

Antwort

27

Ich würde mich nicht zu sehr in der Methode verfangen, die besser ist, weil beide funktionieren und ich beide im Code zuvor benutzt habe.

Zum Beispiel, hier ist eine Nutzenfunktion ich von einem meiner alten Projekte ausgegraben:

/// <summary> 
/// Helper class for SqlDataReader, which allows for the calling code to retrieve a value in a generic fashion. 
/// </summary> 
public static class SqlReaderHelper 
{ 
    private static bool IsNullableType(Type theValueType) 
    { 
     return (theValueType.IsGenericType && theValueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))); 
    } 

    /// <summary> 
    /// Returns the value, of type T, from the SqlDataReader, accounting for both generic and non-generic types. 
    /// </summary> 
    /// <typeparam name="T">T, type applied</typeparam> 
    /// <param name="theReader">The SqlDataReader object that queried the database</param> 
    /// <param name="theColumnName">The column of data to retrieve a value from</param> 
    /// <returns>T, type applied; default value of type if database value is null</returns> 
    public static T GetValue<T>(this SqlDataReader theReader, string theColumnName) 
    { 
     // Read the value out of the reader by string (column name); returns object 
     object theValue = theReader[theColumnName]; 

     // Cast to the generic type applied to this method (i.e. int?) 
     Type theValueType = typeof(T); 

     // Check for null value from the database 
     if (DBNull.Value != theValue) 
     { 
      // We have a null, do we have a nullable type for T? 
      if (!IsNullableType(theValueType)) 
      { 
       // No, this is not a nullable type so just change the value's type from object to T 
       return (T)Convert.ChangeType(theValue, theValueType); 
      } 
      else 
      { 
       // Yes, this is a nullable type so change the value's type from object to the underlying type of T 
       NullableConverter theNullableConverter = new NullableConverter(theValueType); 

       return (T)Convert.ChangeType(theValue, theNullableConverter.UnderlyingType); 
      } 
     } 

     // The value was null in the database, so return the default value for T; this will vary based on what T is (i.e. int has a default of 0) 
     return default(T); 
    } 
} 

Verbrauch:

yourSqlReaderObject.GetValue<int?>("SOME_ID_COLUMN"); 
yourSqlReaderObject.GetValue<string>("SOME_VALUE_COLUMN"); 
+1

Awesome! Ich habe nur eine Empfehlung für die Anpassung an diese .. ändern Sie diese GetValue SqlDataReader zu GetValue (diese IDataRecord – KevinDeus

6

Wenn Sie null überprüfen wollen und damit umgehen (wie Im Gegensatz zur Überprüfung auf Null und der Warnung, dass das Programm null war) können Sie den Operator as mit dem nullverschmelzenden Operator ?? verwenden. Also in meinem Programm

SqlDataReader dr = cmd.ExecuteReader(); 
while (dr.Read()) 
{ 
    response.Employees.Add(new Employee() { Id = dr["id"] as int? ?? default(int), ImageUrl = dr["Photo"] as string, JobTitle = dr["JobTitle"] as string }); 
} 
+0

Ordentlicher Trick, vielen Dank für die Freigabe! – Jocie

1

Hier ist eine einfachere Version von @Karl Anderson Antwort:

public static class DbHelper 
{ 
    public static T GetValue<T>(this SqlDataReader sqlDataReader, string columnName) 
    { 
     var value = sqlDataReader[columnName]; 

     if (value != DBNull.Value) 
     { 
      return (T)value; 
     } 

     return default(T); 
    } 
} 

Oder auch:

public static class DbHelper 
{ 
    public static T GetValue<T>(this SqlDataReader sqlDataReader, string columnName) 
    { 
     var value = sqlDataReader[columnName]; 

     return value == DBNull.Value ? default(T) : (T) value; 
    } 
} 

Angießen scheint ganz gut zu funktionieren entweder auf NULL festlegbare oder Nicht nullfähige Typen

Verwandte Themen