質問
私は頻繁にグリッドコントロールに接続されたデータテーブルに対処する必要があります。カスタム更新は常にdbnull.valueに関連する多くのコードを生成するようです。ここでも同様の質問を見ましたが、より良い答えがなければならないと思います:
私が見つけたのは、私がメソッドのデータベースの更新をカプセル化する傾向があるため、dbnull.valueを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
}
それは、フローの単なる例であり、動作していないコードでした。 「As Type」を使用してDBULLをまっすぐにするために「As Type」を使用して潜在的な鋳造の問題を吸うなどのことができることを理解していますが、これらの両方が潜在的なエラーを隠すように見えます。
タイプの安全性を維持しながらこれを行うためのよりクリーンな方法はありますか?
解決
いくつかの(非常に)単純な一般的なヘルパーメソッドは、少なくともテストを1つのコードに集中させる可能性があります。
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())