Sinceramente imaginei que as coisas seriam mais fáceis quando se trabalha com Nullable Types e base de dados. Hoje estou fazendo alguns testes para entender o comportamento desta nova feature do .NET Framework 2.0. Independente de qualquer coisa que venho a dizer, é de qualquer forma bem legal trabalhar com eles, mas infelizmente quando fui testar a principal utilização do mesmo ao meu ver, que é em conjunto com uma base de dados, fui surpreendido! Explico:
Imaginei eu que poderia fazer algo como:
Dim dr As SqlDataReader = cmd.ExecuteReader()
‘…
Dim dataCompra As Nullable(Of DateTime) = dr.GetDateTime(0)
‘…
If Not dataCompra.HasValue Then MessageBox.Show(“Valor Nulo.”)
Isso seria o ideal ao meu ver, mas quando tentei rodar, me deparei com a seguinte Exception (para minha decepção): System.Data.SqlTypes.SqlNullValueException: Data is Null. This method or property cannot be called on Null values.
Se dermos uma procurada dentro do Reflector pelo método GetDateTime do SqlDataReader, chegamos à função chamada ThrowIfNull(), que atira a exception acima, caso o campo da base de dados que estamos tentando acessar for nulo:
Private Sub ThrowIfNull()
If Me.IsNull Then
Throw New SqlNullValueException
End If
End Sub
Depois disso, resolvi procurar algo no Google a respeito e me deparei com estes dois posts que abordam exatamente isso, ou seja, pelo que entendi, não podemos acessar diretamente os valores nulos da base de dados e atribuirmos aos CLR Nullables Types, sendo necessário uma verificação antes, ficando o código dessa forma:
Dim dr As SqlDataReader = cmd.ExecuteReader()
‘…
Dim dataCompra As Nullable(Of DateTime)
If (Not dr.IsDBNull(0)) Then dataCompra = dr.GetDateTime(0)
‘…
If Not dataCompra.HasValue Then MessageBox.Show(“Valor Nulo.”)
E para piorar, nem o “operador” IIf (no caso do VB.NET) não pode ser utilizado por problemas já reportados anteriormente aqui. A questão é que, se eu tranformar a minha variável dataCompra em um tipo SqlDateTime (tipo que está contido dentro do Namespace System.Data.SqlTypes), eu consigo chegar ao resultado esperado sem problemas:
Dim dr As SqlDataReader = cmd.ExecuteReader()
Dim dataCompra As SqlTypes.SqlDateTime = dr.GetSqlDateTime(0)
If dataCompra.IsNull Then MessageBox.Show(“Valor Nulo.”)
O problema que vejo nisso, é quando vamos atribuir o result-set em um objeto de negócio que temos – quais sempre criamos as suas propriedades com tipos do CLR e não tipos específicos de uma base de dados qualquer – irá obrigar-nos antes de atribuir o valor à mesma, verificar antes se é ou não nulo.