Работа с DBNull.Значение
Мне часто приходится иметь дело с DataTables, подключенными к элементам управления grid, пользовательское обновление всегда производит много кода, связанного с DBNull.Значение. Я видел аналогичный вопрос здесь, но думаю, что должен быть лучший ответ:
что является лучшим способом борьбы с значение dbnull по
Я нахожу, что я склонен инкапсулировать свои обновления базы данных в методы, поэтому я заканчиваю с кодом, как показано ниже, где я перемещаю DBNull.значение для типа nullable, а затем обратно для обновление:
private void UpdateRowEventHandler(object sender, EventArgs e)
{
Boolean? requiresSupport = null;
if (grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport) != DBNull.Value)
requiresSupport = (bool)grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport);
AdditionalSupport.UpdateASRecord(year, studentID, requiresSupport)
}
internal static void UpdateASRecord(
string year,
string studentID,
bool? requiresSupport)
{
List<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@year", SqlDbType.Char, 4) { Value = year });
parameters.Add(new SqlParameter("@student_id", SqlDbType.Char, 11) { Value = studentID });
if (requiresSupport == null)
parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit) { Value = DBNull.Value });
else
parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit) { Value = requiresSupport });
//execute sql query here to do update
}
Это был просто пример потока, а не рабочий код. Я понимаю, что могу делать такие вещи, как передавать объекты или проглатывать потенциальные проблемы с кастингом, используя "как тип", чтобы получить DBUll прямо в null, но оба они мне кажутся скрытыми потенциальными ошибками, мне нравится безопасность типа метода с nullable типами.
есть ли более чистый метод для этого при сохранении безопасности типа?
4 ответов
несколько (очень) простых общих вспомогательных методов могут, по крайней мере, сконцентрировать тест в одном фрагменте кода:
static T FromDB<T>(object value)
{
return value == DBNull.Value ? default(T) : (T)value;
}
static object ToDB<T>(T value)
{
return value == null ? (object) DBNull.Value : value;
}
эти методы могут быть использованы в соответствующих случаях:
private void UpdateRowEventHandler(object sender, EventArgs e)
{
AdditionalSupport.UpdateASRecord(year, studentID,
FromDB<Boolean?>(grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport)));
}
internal static void UpdateASRecord(
string year,
string studentID,
bool? requiresSupport)
{
List<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@year", SqlDbType.Char, 4) { Value = year });
parameters.Add(new SqlParameter("@student_id", SqlDbType.Char, 11) { Value = studentID });
parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit) { Value = ToDB(requiresSupport) });
//execute sql query here to do update
}
Я не вижу, что с as
формы и null
срастанию.
as
-литье используется для чтения:
bool? requiresSupport =
grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport) as bool?;
AdditionalSupport.UpdateASRecord(year, studentID, requiresSupport);
null
объединение используется для написания:
parameters.Add(new SqlParameter("@student_id", SqlDbType.Char, 11)
{ Value = studentID });
parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit)
{ Value = (object)requiresSupport ?? DBNull.Value });
оба они полностью типизированы и не" скрывают " ошибки.
если вы действительно хотите, вы можете оберните их в статические методы, чтобы вы закончили с этим для чтения:
//bool? requiresSupport =
// grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport) as bool?;
bool? requiresSupport = FromDBValue<bool?>(
grdMainLevel1.GetFocusedRowCellValue(colASRequiresSupport));
и этого для пишу:
//parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit)
// { Value = (object)requiresSupport ?? DBNull.Value });
parameters.Add(new SqlParameter("@requires_support", SqlDbType.Bit)
{ Value = ToDBValue(requiresSupport) });
код статического метода немного чище в случае записи, но намерение менее ясно (особенно в случае чтения).
parameters.Add("@requires_support", SqlDbType.Bit).Value = (object)requiresSupport ?? DBNull.Value;
что означает то же самое как
parameters.Add("@requires_support", SqlDbType.Bit).Value = (requiresSupport != null) ? (object)requiresSupport : DBNull.Value;
или
if (requiresSupport != null)
parameters.Add("@requires_support", SqlDbType.Bit).Value = requiresSupport
else
parameters.Add("@requires_support", SqlDbType.Bit).Value = DBNull.Value;
(для удаления неоднозначности типа требуется дополнительное приведение к объекту)
public static object DbNullable<T>(T? value) where T : struct
{
if (value.HasValue)
{
return value.Value;
}
return DBNull.Value;
}
public static object ToDbNullable<T>(this T? value) where T : struct
{
return DbNullable(value);
}
Это моя реализация помощника DBNULL. Использование просто:
new SqlParameter("Option1", option1.ToDbNullable())