题
我经常不得不处理连接到网格控件的数据表,自定义更新似乎总是会产生与dbnull.value相关的许多代码。我在这里看到了一个类似的问题,但认为必须有一个更好的答案:
我发现的是,我倾向于将数据库更新封装在方法中,因此我最终以下面的代码将dbnull.value移动到可取消的类型,然后返回以进行更新:
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
}
这只是流的一个示例,而不是工作代码。我意识到我可以使用“ AS Type”将dbull直接送至null之类的吞咽对象或吞咽潜在的铸造问题,但对我来说这两种问题似乎都隐藏了潜在的错误,我喜欢这种方法的类型安全性,可通过可用类型的类型。
在维持类型安全性的同时,是否有更干净的方法可以做到这一点?
解决方案
几个(非常)简单的通用辅助方法至少可能将测试集中在一件代码中:
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())
不隶属于 StackOverflow