Какова наилучшая практика для обработки null int / char из базы данных SQL?
-
11-07-2019 - |
Вопрос
У меня есть база данных, в которой хранится необязательный профиль пользователя.В профиле у меня есть строки, символы (для M или F) и целые числа.
Я столкнулся с проблемой, когда я пытаюсь указать пол пользователя в свойстве моего объекта Profile, и приложение выходит из строя, потому что оно не знает, как обрабатывать возвращаемое нулевое значение.
Я попытался привести данные к соответствующему типу
char sex = (char)dt.Rows[0]["Sex"];
Что не решило мою проблему.Затем я попытался изменить типы на Nullable и Nullable и все равно получил проблемы с преобразованием.Мое текущее решение, которое мне удалось найти, заключается в следующем:
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"];
Есть ли более простой или лучший способ сделать это?Или я в значительной степени на правильном пути?
Решение
ответ Ротарда (используйте Is<ColumnName>Null()
) работает только для типизированных наборов данных. Р>
Для нетипизированных наборов данных вы должны использовать один из шаблонов в следующем коде. Если этот код не является окончательным, дайте мне знать, и я буду редактировать его, пока он не будет. Это чрезвычайно распространенный вопрос, на который действительно должен быть только один правильный ответ.
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();
}
}
Другие советы
Обнуляемые типы были разработаны специально для этой цели! использовать в качестве символа? вместо '(char?)'
class Foo {
char? sex;
}
Foo object;
object.sex = dt.Rows[0]["Sex"] as char?;
Достойное обсуждение этого вопроса можно найти по адресу Наиболее эффективный способ проверить наличие DBNull и назначить его переменной? .
Является ли dt таблицей данных ADO.Net 2?Разве вы не можете сделать что-то вроде:
if(dt.Rows[0].IsSexNull()) {} else {}
?Кроме того, предполагая, что у вас есть контроль над вашей базой данных, не имеет ли смысла использовать бит, а не строку?
как насчет:
internal static T CastTo<T>(object value)
{
return value != DBNull.Value ? (T)value : default(T);
}
а затем используйте его как:
return new EquipmentDetails(
CastTo<int>(reader["ID"]),
CastTo<int>(reader["CategoryID"]),
CastTo<string>(reader["Description"]));
и т.д...
Я бы сделал это почти так же, как ты. Я бы написал для него функцию:
Что-то, что делает:
object.sex = handle(dt.Rows[0]["Sex"]);
А в дескрипторе вы делаете проверку == DBNull.Value.