Há muitas respostas aqui com informações úteis (e algumas informações erradas) espalhadas, eu gostaria de reunir tudo.
A resposta curta para a pergunta é verificar o DBNull - quase todo mundo concorda com esse bit :)
Em vez de usar um método auxiliar para ler valores anuláveis por tipo de dados SQL, um método genérico nos permite abordar isso com muito menos código. No entanto, você não pode ter um único método genérico para os tipos de valor anulável e de referência. Isso é discutido detalhadamente no
tipo Nullable como um parâmetro genérico possível. e restrição de tipo genérico C # para tudo que pode ser anulado .
Portanto, seguindo as respostas de @ZXX e @getpsyched, terminamos com dois métodos para obter valores anuláveis e adicionei um terceiro para valores não nulos (ele completa o conjunto com base na nomeação de métodos).
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);
}
Eu geralmente uso nomes de colunas, altere-os se você usar índices de colunas. Com base nesses nomes de método, posso dizer se estou esperando que os dados sejam anuláveis ou não, o que é bastante útil quando se olha o código escrito há muito tempo.
Dicas;
- Não ter colunas anuláveis no banco de dados evita esse problema. Se você tiver controle sobre o banco de dados, as colunas deverão ser não nulas por padrão e somente nulas quando necessário.
- Não converta valores de banco de dados com o operador C # 'as' porque, se a conversão estiver incorreta, ela retornará silenciosamente nulo.
- O uso de uma expressão de valor padrão alterará os valores nulos do banco de dados para valores não nulos para tipos de valores como int, datetime, bit etc.
Por fim, ao testar os métodos acima em todos os tipos de dados do SQL Server, descobri que você não pode obter diretamente um char [] de um SqlDataReader; se você quiser um char [], precisará obter uma string e usar ToCharArray ().
int colIndex = reader.GetOrdinal(fieldname);
e sobrecarregar facilmente aSafeGetString
função de @ marc_s .