Qual è la procedura migliore per gestire null int/char da un database SQL?
-
11-07-2019 - |
Domanda
Ho un database che contiene il profilo opzionale di un utente.Nel profilo ho stringhe, char (per M o F) e int.
Ho riscontrato un problema in cui provo a inserire il sesso dell'utente nella proprietà del mio oggetto Profile e l'applicazione si blocca perché non sa come gestire un valore null restituito.
Ho provato a trasmettere i dati al tipo appropriato
char sex = (char)dt.Rows[0]["Sex"];
Il che non ha risolto il mio problema.Ho quindi provato a modificare i tipi in Nullable e Nullable e ho riscontrato comunque problemi di conversione.La mia soluzione attuale che sono riuscito a trovare è la seguente:
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"];
Esiste un modo più semplice o migliore per farlo?Oppure sono più o meno sulla strada giusta?
Soluzione
risposta di rotard (usare Is<ColumnName>Null()
) funziona solo per set di dati tipizzati.
Per i set di dati non tipizzati, devi utilizzare uno dei modelli nel codice seguente.Se questo codice non è definitivo, fammelo sapere e lo modificherò finché non lo sarà.Questa è una domanda estremamente comune alla quale dovrebbe esserci una sola risposta giusta.
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();
}
}
Altri suggerimenti
I tipi nullable sono stati progettati proprio per questo scopo! usa "come carattere?" anziché "(char?)"
class Foo {
char? sex;
}
Foo object;
object.sex = dt.Rows[0]["Sex"] as char?;
Una discussione decente su questo è su Il modo più efficiente per verificare DBNull e quindi assegnarlo a una variabile? .
Dt è una tabella di dati ADO.Net 2? Non puoi fare qualcosa del genere:
if(dt.Rows[0].IsSexNull()) {} else {}
? Inoltre, supponendo che tu abbia il controllo sul tuo database, non avrebbe più senso usare un po ', piuttosto che una stringa?
che ne dici di:
internal static T CastTo<T>(object value)
{
return value != DBNull.Value ? (T)value : default(T);
}
e poi usalo come:
return new EquipmentDetails(
CastTo<int>(reader["ID"]),
CastTo<int>(reader["CategoryID"]),
CastTo<string>(reader["Description"]));
ecc ...
Lo farei praticamente come hai fatto tu. Vorrei scrivere una funzione per questo:
Qualcosa che fa:
object.sex = handle(dt.Rows[0]["Sex"]);
E in handle fai il controllo == DBNull.Value.