良い一日、
[〜#〜] ide [〜#〜]Visual Studio 2010
。NET3.5
プラットフォームWinForms
SO質問 " DataRowからの値の取得の違い "が参照します。
[ID] INT IDENTITY(1, 1) NOT NULL PRIMARY KEY
列のデータベーステーブルがあります。このテーブルをクエリしてローカル変数に値を格納すると、無効なキャスト例外が発生します。サンプルコード:
_string sQuery = @"
SELECT [ID], [Description]
FROM [Sources]
ORDER BY [Description] ";
using (DataTable dtSources = SQLHelper.Fetch(sQuery))
{
foreach (DataRow drSource in dtSources.Rows)
{
int iID = drSource.Field<int>("ID"); // InvalidCastException
string sDescrption = drSource.Field<string>("Description");
}
}
_
実行をステップ実行し、障害のある行で「クイックウォッチ」を実行すると、行をdrSource.Field<object>("ID")
に変更することにより、セル値のタイプがshort
ではなくint
のタイプであることがわかりました。テーブル定義で、これが明らかにint
であるのに、なぜこれが発生するのでしょうか。さらに、short
はより小さく、正しく「適合する」必要があるため、int
は暗黙的にshort
に変換する必要がありますか?
好奇心から、キー/値コレクションから明示的にキャストするとどうなりますか?
int iID = (int)drSource["ID"];
列がnull許容のintであるが、デフォルト値0でintに割り当てようとしている場合:
using (DataTable dtSources = SQLHelper.Fetch(sQuery))
{
foreach (DataRow drSource in dtSources.Rows)'
{
int iID = drSource.Field<int?>("ID") ?? 0;
string sDescrption = drSource.Field<string>("Description");
}
}
列がnull許容のintであり、null許容のintに割り当てたい場合:
using (DataTable dtSources = SQLHelper.Fetch(sQuery))
{
foreach (DataRow drSource in dtSources.Rows)
{
int? iID = drSource.Field<int?>("ID");
string sDescrption = drSource.Field<string>("Description");
}
}
リチャードの答えに同意してください。
int iID = Convert.ToInt32(drSource["ID"]);
フィールド拡張の実装によると、フィールドにはDbNull値があります。
public static T Field<T>(this DataRow row, string columnName)
{
DataSetUtil.CheckArgumentNull<DataRow>(row, "row");
return UnboxT<T>.Unbox(row[columnName]);
}
UnboxTは、オブジェクトをTに変換するためのメソッドを提供するプライベートクラスです。この場合、ValueFieldコンバーターが使用されます。
private static class UnboxT<T>
{
internal static readonly Converter<object, T> Unbox;
static UnboxT()
{
DataRowExtensions.UnboxT<T>.Unbox =
new Converter<object, T>(DataRowExtensions.UnboxT<T>.ValueField);
}
private static T ValueField(object value)
{
if (DBNull.Value == value)
{
// You get this exception
throw DataSetUtil.InvalidCast(Strings.DataSetLinq_NonNullableCast(typeof(T).ToString()));
}
return (T) value;
}
}
行の値をint変数に変換する別の方法は、「object」を使用して、次のようにInt32に変換することです。
int iID = Convert.ToInt32(row.Field<object>("ID"));