いくつかの列があるDataTableがあります。これらの列の一部はNULL可能です。
_DataTable dt; // Value set.
DataRow dr; // Value set.
// dr["A"] is populated from T-SQL column defined as: int NULL
_
次に、DataRowの値からnull可能な変数に変換する最もクリーンな形式は何ですか。
理想的には、私は次のようなことができるでしょう:
_int? a = dr["A"] as int?;
_
Edit:これを実行できることがわかります。スキーマ型は整数ではないので、これは常にnullを返します。 Rubenによるdr.Field<int?>("A")
の使用の答えは、型の不一致が暗黙のうちに失敗しないことを保証します。もちろん、これは完全な単体テストで取り上げられます。
代わりに、私は通常、次の行に沿って何かを入力しています:
_int? a = dr["A"] != DBNull.Value ? (int)dr["A"] : 0;
_
これはかなり多くのキーストロークですが、さらに重要なことに、誰かが間違ったキーストロークで何かを詰め込む余地がより多くあります。はい、単体テストはこれを拾いますが、私はむしろそれを完全に止めたいです。
この状況で最もクリーンでエラーが発生しにくいパターンは何ですか。
LINQ in ActionのLINQ to DataSetsの章 は良い読み物です。
表示されるのはField<T>
拡張メソッド。次のように使用されます:-
int? x = dr.Field<int?>( "Field" );
または
int y = dr.Field<int?>( "Field" ) ?? 0;
または
var z = dr.Field<int?>( "Field" );
これが.NET 3.5のDataRowExtensions
クラスの目的です。これは、DataRow
と.NET型の間でnull可能(およびnull不可)データをラウンドトリップするための静的Field<T>
およびSetField<T>
メソッドを提供します。
int? fld = row.Field<int?>("ColumnA")
row["ColumnA"]
にDBNull.Value
が含まれている場合はfld
をnull
に設定し、整数が含まれている場合はその値に設定し、それ以外に何かが含まれている場合は例外をスローします。そして帰る途中で
row.SetField("ColumnA", fld);
同じことを逆に行います。fld
にnull
が含まれている場合、row["ColumnA"]
をDBNull.Value
に設定し、それ以外の場合はfld
の値に設定します。
Field
がサポートするすべての値の型(null不可の型を含む)にはSetField
とDataRow
のオーバーロードがあるため、取得と設定に同じメカニズムを使用できますデータ型に関係なくフィールド。
int? a = (int?)dr["A"]
以下は安全に機能します:
スニップ:
public static class SqlDataReaderEx
{
public static int TryParse(SqlDataReader drReader, string strColumn, int nDefault)
{
int nOrdinal = drReader.GetOrdinal(strColumn);
if (!drReader.IsDbNull(nOrdinal))
return drReader.GetInt32(nOrdinal);
else
return nDefault;
}
}
使用法:
SqlDataReaderEx.TryParse(drReader, "MyColumnName", -1);
なぜLINQを使わないのですか?それはあなたのために変換を行います。
拡張メソッド!
次のようなもの:
public static class DataRowExtensions
{
public static Nullable<T> GetNullableValue<T>(this DataRow row, string columnName)
where T : struct
{
object value = row[columnName];
if (Convert.IsDBNull(value))
return null;
return (Nullable<T>)value;
}
public static T GetValue<T>(this DataRow row, string columnName)
where T : class
{
object value = row[columnName];
if (Convert.IsDBNull(value))
return null;
return (T)value;
}
}
次のように使用します。
int? a = dr.GetNullableValue<int>("A");
または
string b = dr.GetValue<string>("B");