C#でDBNullチェック時にエラーを出さずにキャストする最適解

この記事は約 3 分で読めます。

C#でDBのデータを取得する際に厄介なのがDBNull。。

DBNullはNullとは別物のため、Null判定できません。

故に三項演算子などを使ってDBNull回避する必要があります。

そこでDBNullをうまく回避しつつ、同時にキャストしてくれる関数を作れないか?と考えたところ。

私の中での最適解が生まれたので書いていきます。

        public static T Convert<T>(object obj)
        {
            if (obj != DBNull.Value && obj != null)
            {
                return (T) obj;
            }

            return default;
        }

object型は何でも受け取ることができます。

なので一度Object形で受け取り、DBNullとNullでないことをチェックします。

DBNullでもNullでもなければ、指定の型にキャストします。

Nullだった場合Defaultを返します。

これでDBNullをきれいに回避することができるのではないでしょうか??

この関数の使い方は下記のようになります。(SqlDataReaderで書いていきますが、DataRowでも使えると思います。)

                    using (var dataReader = command.ExecuteReader())
                    {
                        if (dataReader.HasRows)
                        {
                            while (dataReader.Read())
                            {
                               var username = Convert<string>(reader["UserName"]);
                               var userId = Convert<string>(reader["UserId"]);
                               var userpass = Convert<string>(reader["UserPass"]);
                               var roleId = Convert<int>(reader["RoleId"]);
                            }
                        }
                    }

キャストしたい型を指定して、引数にreaderのItemを投げればうまくできますね!

拡張メソッドを使えば下記のようにできますが、すべての型で拡張されてしまうので、推奨はしません。

拡張メソッドで書いてみる

    public static class ObjectHelper
    {
        public static T ReplaceDBNull<T>(this object obj)
        {
            if (obj != DBNull.Value && obj != null)
            {
                return (T) obj;
            }

            return default;
        }
    }

こんな感じで書くと以下のような形で使えます。

                    using (var dataReader = command.ExecuteReader())
                    {
                        if (dataReader.HasRows)
                        {
                            while (dataReader.Read())
                            {
                               var username = reader["UserName"].ReplaceDBNull<string>();
                               var userId = reader["UserId"].ReplaceDBNull<string>();
                               var userpass = reader["UserPass"].ReplaceDBNull<string>();
                               var roleId = reader["RoleId"].ReplaceDBNull<int>();
                            }
                        }
                    }

この方法は推奨はしません。

何故ならObject型はすべての型が継承している型になっています。

それすなわち全ての型にReplaceDBNullが実装されるということになります。

個人開発ならまだいいかもしれませんが、みんなで使う際は避けたほうがいいかもしれませんね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA