Aquí hay muchas respuestas con información útil (y alguna información incorrecta), me gustaría reunir todo.
La respuesta corta a la pregunta es verificar DBNull: casi todos están de acuerdo con este bit :)
En lugar de utilizar un método auxiliar para leer valores anulables por tipo de datos SQL, un método genérico nos permite abordar esto con mucho menos código. Sin embargo, no puede tener un único método genérico tanto para los tipos de valores anulables como para los tipos de referencia, ¿esto se discute extensamente en el
tipo Nullable como un parámetro genérico posible? y restricción de tipo genérico C # para todo lo que se puede anular .
Entonces, siguiendo las respuestas de @ZXX y @getpsyched, terminamos con esto, 2 métodos para obtener valores anulables y he agregado un tercero para valores no nulos (completa el conjunto basado en el nombre del método).
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);
}
Usualmente uso nombres de columna, modifíquelos si usa índices de columna. En base a estos nombres de métodos, puedo decir si espero que los datos sean anulables o no, bastante útil cuando se mira el código escrito hace mucho tiempo.
Consejos;
- No tener columnas anulables en la base de datos evita este problema. Si tiene control sobre la base de datos, las columnas deben ser no nulas por defecto y solo anulables cuando sea necesario.
- No convierta los valores de la base de datos con el operador C # 'as' porque si la conversión es incorrecta, silenciosamente devolverá nulo.
- El uso de una expresión de valor predeterminada cambiará los valores nulos de la base de datos a valores no nulos para tipos de valores como int, datetime, bit, etc.
Por último, al probar los métodos anteriores en todos los tipos de datos de SQL Server descubrí que no puede obtener directamente un char [] de un SqlDataReader, si desea un char [] tendrá que obtener una cadena y usar ToCharArray ().
int colIndex = reader.GetOrdinal(fieldname);
y sobrecargar fácilmente laSafeGetString
función de @ marc_s .