Ci sono molte risposte qui con informazioni utili (e alcune informazioni sbagliate) sparse, mi piacerebbe riunire tutto.
La risposta breve alla domanda è verificare DBNull - quasi tutti sono d'accordo su questo bit :)
Invece di utilizzare un metodo di supporto per leggere valori nullable per tipo di dati SQL, un metodo generico ci consente di risolvere questo problema con molto meno codice. Tuttavia, non è possibile disporre di un singolo metodo generico sia per i tipi di valori annullabili sia per i tipi di riferimento, questo è discusso a lungo nel
tipo Nullable come parametro generico possibile? e vincolo di tipo generico C # per tutto nullable .
Quindi, seguendo le risposte di @ZXX e @getpsyched, finiamo con questo, 2 metodi per ottenere valori nullable e ho aggiunto un terzo per valori non nulli (completa il set in base alla denominazione del metodo).
public static T? GetNullableValueType<T>(this SqlDataReader sqlDataReader, string columnName) where T : struct
{
int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
return sqlDataReader.IsDBNull(columnOrdinal) ? (T?)null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}
public static T GetNullableReferenceType<T>(this SqlDataReader sqlDataReader, string columnName) where T : class
{
int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
return sqlDataReader.IsDBNull(columnOrdinal) ? null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}
public static T GetNonNullValue<T>(this SqlDataReader sqlDataReader, string columnName)
{
int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
return sqlDataReader.GetFieldValue<T>(columnOrdinal);
}
Di solito uso i nomi di colonna, li altero se usi gli indici di colonna. Sulla base di questi nomi di metodi, posso dire se mi aspetto che i dati siano nulli o meno, molto utili quando si guarda il codice scritto molto tempo fa.
Suggerimenti;
- Non avere colonne nullable nel database evita questo problema. Se si ha il controllo sul database, le colonne dovrebbero essere non nulle per impostazione predefinita e annullabili solo se necessario.
- Non eseguire il cast dei valori del database con l'operatore C # 'as' poiché, se il cast è errato, restituirà automaticamente null.
- L'uso di un'espressione di valore predefinita cambierà i valori nulli del database in valori non nulli per tipi di valore come int, datetime, bit ecc.
Infine, durante il test dei metodi di cui sopra su tutti i tipi di dati di SQL Server ho scoperto che non è possibile ottenere direttamente un carattere [] da un SqlDataReader, se si desidera un carattere [], sarà necessario ottenere una stringa e utilizzare ToCharArray ().
int colIndex = reader.GetOrdinal(fieldname);
e sovraccaricare facilmente laSafeGetString
funzione di @ marc_s .