2013-08-31 19 views
9

Desidero recuperare i valori decimali dal database e vorrei sapere qual è il metodo consigliato per verificare i valori nulli.SqlDataReader Il modo migliore per verificare valori nulli -sqlDataReader.IsDBNull vs DBNull.Value

Ho visto su MSDN - DBNull.Value Field che questo controllo è usato raramente.

Quindi, è il reader.IsDBNull il modo migliore/più efficace per verificare i valori nulli?

ho creato 2 metodi di campionamento:

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

maggior parte del tempo i campi stanno per essere nullo.

Grazie in anticipo!

+0

Quale mai preferisci e trova più leggibile. Tuttavia, vale la pena notare che i vostri esempi non sono strettamente equivalenti dato l'uso di 'reader.GetOrdinal' nel secondo. –

+1

Il 'sintassi' reader [nomeCampo] 'è risolto internamente a' reader.GetOrdinal (fieldName) ' – Steve

+0

Ho modificato l'esempio per usare reader [fieldName] in entrambi i casi – diver

risposta

27

Non vorrei essere troppo preso dal metodo che è migliore, perché entrambi funzionano e ho usato entrambi in codice prima.

Per esempio, qui è una funzione di utilità ho scavato da uno dei miei vecchi progetti:

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

Usage:

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

Awesome! Ho solo una raccomandazione per la regolazione di questo .. cambiare questo GetValue SqlDataReader per GetValue (questo IDataRecord – KevinDeus

6

Se si desidera controllare per nulla e gestire (come opposto al controllo per null e allertando il programma che era nullo) è possibile utilizzare l'operatore as con l'operatore con coalizione nulla ??. Così nel mio programma

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

Trucchetto Neat, grazie per la condivisione! – Jocie

1

Ecco una versione più semplice di risposta di @Karl Anderson:

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

O anche:

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

getto diretto sembra funzionare bene per sia annullabile o tipi non annullibili.