Qual é a melhor prática para lidar com nulo int / char de um banco de dados SQL?
-
11-07-2019 - |
Pergunta
Eu tenho um banco de dados que espera é o perfil opcional de um usuário. No perfil eu têm cordas, carvão animal (por H ou F) e ints.
Eu corri para um problema onde eu tento colocar o sexo do usuário para a propriedade de meu objeto Perfil, ea aplicação deixa de funcionar porque não sabem como lidar com um valor nulo retornado.
Eu tentei lançar os dados para o tipo apropriado
char sex = (char)dt.Rows[0]["Sex"];
O que não resolver o meu problema. Então eu tentei alterar os tipos de Nullable e Nullable e tenha problemas de conversão todos o mesmo. Minha solução atual que eu era capaz de encontrar é o seguinte:
object.sex = null;
if(dt.Rows[0]["Sex"] != DBNull.Value)
object.sex = (char)dt.Rows[0]["Sex"];
object.WorkExt = null;
if(dt.Rows[0]["WorkExt"] != DBNull.Value)
object.WorkExt = (int)dt.Rows[0]["WorkExt"];
Existe uma maneira mais simples ou melhor de fazer isso? Ou eu sou muito bem no caminho certo?
Solução
A resposta de rotard (uso Is<ColumnName>Null()
) só funciona para conjuntos de dados digitados.
Para conjuntos de dados sem tipo, você tem que usar um dos padrões no código a seguir. Se este código não é definitivo, deixe-me saber e eu vou editá-lo até que ele é. Esta é uma questão extremamente comum que não deve realmente ser apenas uma resposta certa a.
using System.
using System.Data;
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("test", typeof (char));
dt.Columns["test"].AllowDBNull = true;
DataRow dr = dt.Rows.Add();
char? test;
try
{
test = (char?)dr["test"];
}
catch (InvalidCastException)
{
Console.WriteLine("Simply casting to a nullable type doesn't work.");
}
test = dr.Field<char?>("test");
if (test == null)
{
Console.WriteLine("The Field extension method in .NET 3.5 converts System.DBNull to null.");
}
test = (dr["test"] is DBNull) ? null : (char?) dr["test"];
if (test == null)
{
Console.WriteLine("Before .NET 3.5, you have to check the type of the column's value.");
}
test = (dr["test"] == DBNull.Value) ? null : (char?) dr["test"];
if (test == null)
{
Console.WriteLine("Comparing the field's value to DBNull.Value is very marginally faster, but takes a bit more code.");
}
// now let's put the data back
try
{
dr["test"] = test;
}
catch (ArgumentException)
{
Console.WriteLine("You can't set nullable columns to null.");
}
dr.SetField("test", test);
if (dr["test"] is DBNull)
{
Console.WriteLine("Again, in .NET 3.5 extension methods make this relatively easy.");
}
dr["test"] = (object)test ?? DBNull.Value;
if (dr["test"] is DBNull)
{
Console.WriteLine("Before .NET 3.5, you can use the null coalescing operator, but note the awful cast required.");
}
Console.ReadLine();
}
}
Outras dicas
tipos anuláveis ??foram projetados apenas para esta finalidade! usar 'como char? em vez de '(char?)'
class Foo {
char? sex;
}
Foo object;
object.sex = dt.Rows[0]["Sex"] as char?;
Uma discussão decente sobre esta é a a forma mais eficiente para verificar DBNull e depois atribuir a uma variável? .
É dt uma tabela de dados ADO.Net 2? você não pode fazer algo como:
if(dt.Rows[0].IsSexNull()) {} else {}
? Além disso, supondo que você tem controle sobre o seu banco de dados, não faria mais sentido usar um pouco, em vez de uma string?
como sobre: ??
internal static T CastTo<T>(object value)
{
return value != DBNull.Value ? (T)value : default(T);
}
e, em seguida, usá-lo como:
return new EquipmentDetails(
CastTo<int>(reader["ID"]),
CastTo<int>(reader["CategoryID"]),
CastTo<string>(reader["Description"]));
etc ...
Eu faria isso muito bonito como você fez. Eu ia escrever uma função para isso:
Algo que faz:
object.sex = handle(dt.Rows[0]["Sex"]);
E em punho você fazer o check == DBNull.Value.