C# DataRowの値を取り出すときにDBNullでエラーを出さない。

DataRowから値を読み込むとき、 たとえば、

と適当にDataRowを用意して、

と読み取ろうとすると、
「型 ‘System.InvalidCastException’ のハンドルされていない例外が mscorlib.dll で発生しました」
「追加情報:オブジェクトを DBNull から他のタイプにキャストすることはできません。」
と叱られます。

これは、dr[“id”]などのDataRowの値がNullだからです。

そこで、dr[“id”]の値がNullかどうかを調べる必要があるわけですが、if (dr[“id”]!=null) とやっても、dr[“id”]そのものはNullではないのでうまく行きません。

dr[“id”]の値がNullかどうかは、if (!dr.IsNull(“id”)) とか、if (dr!=DBNull.Value) のようにするといいわけですが、IF文を大量に並べるのはちょっと見苦しいですよね。

DBNull.Value.Equalsと三項演算子で処理する

そこで、DBNull.Value.Equalsを使って、DataRowのカラムの値がnullなら、三項演算子で任意の値を入れるようにします。

とすると、DBNullのときでもエラーが出ません。 DBNull.Value.Equals は、内容DBNullかどうかをチェックしてDBNullならTrueを返します。

DataRow.Fieldとnull 合体演算子で処理する

でも、あんまりスマートな書き方でないので、調べたら .Net Framework3.5からこんな書き方ができるようになっていました。

dr.Field(“id”) で、dr[“id”]の中身を取り出してくれます。
UInt64? の ? は、Nullable型とすることを表して、Null非許容型に対してNullを入れられるようにします。String はもともとNull許容型なので、?はつけません。
?? はNullかどうかを判定する演算子で、Nullなら、別の値をいれることができます。

なので、 UInt64 id = dr.Field(“id”)??0; は、dr[“id”]の内容がDBNullならnullとし、その場合0をidに入れる、ということになります。

さらに、defaultで初期値を取得すれば、書き方を定型化できます。

 

DataRowの値を取得する関数を作る

いちいちFieldを使うのも面倒なので、個人的には次のように関数化してつかってます。

こんな感じで使います。

 

ちなみに、MySQLのtinyint型の場合は、byteとして取り込まれるので、つぎのようにして取得します。

 

タイトルとURLをコピーしました