QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

[vb.net]DBNULLについて質問

こんにちわ。質問ですが、あるテーブルの情報を取得して、
変数(今回はstring型)にマッピングする際、もしテーブル内項目に値が入ってない場合は
「型 'DBNull' から型 'String' へのキャストが有効ではありません。"」と怒られます。
もちろん当然なので、今まで私の対処方としては



dim strID as string
dataReader.Read
if dataReader("ID").GetType.FullName = "System.DBNull" then 
   strID = ""
else
   strID = dataReader("ID")
end if

と行っておりました。
しかし、dataReader("ID")の内容をそのまま別のクラスのコンストラクタに
セットしたい場合は、この方法では無理です。

==>やりたいこと。



'//I責務:Dを保持するクラス
class IDinfo
    private ID as string

    'コンストラクタ
    public sub new(ByVal id As String)
        Me.ID = id
    end sub

    'プロパティ
    public property pID as string
        get
           pID = Me.ID
        end get
        set(ByVal Value As string)
           ID = Value
        end set
    end property
end class

'//責務:IDinfoクラスにdataReaderから値をセットするクラス
'//
class IDinfoSet
    public function CreateTBLCollection(dataReader as IDataReader) as ArrayList

        dim IdCollection as ArrayList = new ArrayList()

        '//EofまでRead
        do until dataReader.Read = False

           '=====>>問題個所 
           Dim sIIDinfo as IDinfo = new IDinfo(dataReader("ID"))
           '※㊤の文でdataReader("ID")がNullの場合、DBNULLだと怒られるが、
      'なんとかコンストラクタでセットしたい。
           '<<=========

           IdCollection.Add(sIIDinfo)
        loop

        '//IDコレクションを返す
        return IdCollection

    end function
end class

というようなことがしたいのですが、、、初心者な質問ですみません。
みなさんどう解決されてますか?? ご教授お願いします。

質問者:hiro

回答

 SQL関数で読み替えるだけでは?※通常DBには列の値がnullかどうか判断して、
 値を置き換えるSQL関数が用意されています。

投稿者:taku

編集 履歴 (0)



   '=====>>問題個所 
           Dim sIIDinfo as IDinfo = new IDinfo(dataReader("ID"))
           '※㊤の文でdataReader("ID")がNullの場合、DBNULLだと怒られるが、
      'なんとかコンストラクタでセットしたい。
           '<<=========



        Dim sIIDInfo As IDInfo

        If TypeOf dataReader("ID") Is DBNull Then
            sIIDInfo = New IDinfo("")
        Else
            sIIDInfo = New IDinfo(dataReader("ID"))
        End If

もしくは



        Dim sIIDInfo As new IDInfo(IIf(TypeOf dataReader("ID") Is DBNull, "", dataReader("ID") )

もしくは



        Dim sIIDInfo As new IDInfo(IIf(dataReader.IsDBNull(項目IDを示すindex), "", dataReader("ID") )

では駄目なのでしょうか?

#3つ目の例示に間違いがあったので修正しました。

[ メッセージ編集済み 編集者: NAL-6295 編集日時 2004-01-23 18:57 ]

投稿者:NAL-6295

編集 履歴 (0)

NAL-6295さんの書き込み (2004-01-23 18:10) より:

 IIF関数?!がーん!!if文で5行使ってやっていたのに・・・

投稿者:Jitta

編集 履歴 (0)

みなさん、書込みありがとうございました。
NAL-6295さんの方法でやると解決しました。
本当に感謝します。

#IIF関数の存在は知ってたのですが、引数に入れることは
#思いつきませんでした;; もうvb5年もやってるのに。。

また何か有ればぜひよろしくお願いします。

投稿者:hiro

編集 履歴 (0)

IIf関数は便利なんですが、Option Strict On で開発してると使いにくいんですね〜

あと、今回では問題ないですが、IIf関数は C# などの3項演算子と異なり、両方の式を評価するので注意が必要だったりします。
# これが原因でInvalidCast〜とかNullReference〜とか…

投稿者:なちゃ

編集 履歴 (0)

なちゃさんの書き込み (2004-01-23 18:43) より:

IIf関数は便利なんですが、Option Strict On で開発してると使いにくいんですね〜

あと、今回では問題ないですが、IIf関数は C# などの3項演算子と異なり、両方の式を評価するので注意が必要だったりします。

これが原因でInvalidCast〜とかNullReference〜とか…

フォローありがとうございます。
確かにそうですね。
最初に提示したIFでやる方をお勧めしたいですね。
個人的にはIIFはどちらが評価されてもいい局面でのみ使用するようにしています。

投稿者:NAL-6295

編集 履歴 (0)

全然はずしているかもしれませんが、
Dim sIIDInfo As new IDInfo(dataReader("ID") & "")
というのは、どうですか?

投稿者:たるたる

編集 履歴 (0)

たるたるさんの書き込み (2004-01-23 21:35) より:

全然はずしているかもしれませんが、

Dim sIIDInfo As new IDInfo(dataReader("ID") & "")

というのは、どうですか?

その場合、dataReader("ID")の内容がDBNullだと
InvaridCast〜
な例外が発生します。

・・・と思ったら、うまくいくようでした。すいません。
[ メッセージ編集済み 編集者: NAL-6295 編集日時 2004-01-24 15:21 ]

投稿者:NAL-6295

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。