3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援→開発戻り浦島太郎状態の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。

(Ado.Net)DataSetが作るRowオブジェクトのフィールドプロパティに要注意

DataSetって便利なんですが、裏っかわの仕様をよく理解してないと痛い目にあいます。

今回は型でやられました。

VisualStudio のサーバーエクスプローラからDBの Account というテーブルをDataSetのデザイナにドラッグして下記のようなDataSetを作ります。

このとき、親切すぎる VisualStudio のデザイナはDataTableのみならず、DataRow まで勝手に作ってくれます。

で、この勝手に作ってくれた DataRow(上記のテーブルだと AccountRow)を使うと各カラムへのアクセスがプロパティとして用意されているんですよね。

これを使うと簡単に DataTable 内の目的のデータにアクセスできます。

たとえば DataRow("列名") と書いてたのが DataRow.列名 という感じになります。

それで、今回は下記のようなコードを書いていました。

Dim m_adpAccount As New RhythmSalesProDataSetTableAdapters.AccountTableAdapter()

Dim m_tblAccount As RhythmSalesProDataSet.AccountDataTable = m_adpAccount.GetData()

If m_tblAccount.Count < 1 Then

MessageBox.Show("データなし")

Else

Dim row As TestDataSet.AccountRow = m_tblAccount.Rows(0)

Dim name As String

If row.UserName Is DBNull.Value Then

name = String.Empty

Else

name = row.UserName

End If

End If

データベースから取得してローカル変数に代入する簡単なものですが、DBの値が null のとき If row.UserName Is DBNull.Value Then のところで DBNull ていう例外になるんですよね。

よく考えたらこの TestDataSet.AccountRow.UserName というプロパティ文字列型になっています。ということは中身が DBNull の時点で取得しようとするとプロパティのゲッターの中で例外になるわけですわ。

このプロパティは VisualStudio が勝手に吐いたものなので、DataSet の Designer ファイルをのぞいてみました。

System.Diagnostics.DebuggerNonUserCodeAttribute()> _

Public Property UserName() As String

Get

Try

Return CType(Me(Me.tableAccount.UserNameColumn),String)

Catch e As Global.System.InvalidCastException

Throw New Global.System.Data.StrongTypingException("テーブル 'Account' にある列 'UserName' の値は DBNull です。", e)

End Try

End Get

Set

Me(Me.tableAccount.UserNameColumn) = value

End Set

End Property

やはり文字列にキャストできないときは例外をスローするようになっています。

ということは結局 DataRow("列名") で DBNull かどうか判断せんといかんのかと思いましたが、VisualStuido が勝手に吐くコードの中にこんなメソッドがありました。

Public Function IsUserNameNull() As Boolean

Return Me.IsNull(Me.tableAccount.UserNameColumn)

End Function

どうやらこのメソッドを使えば DBNull を意識しなくてもいいようです。

最終的に下記のように IsUserNameNull() を使って判定するよう修正しました。

Dim row As TestDataSet.AccountRow = m_tblAccount.Rows(0)

Dim name As String

If row.IsUserNameNull() Then

name = String.Empty

Else

name = row.UserName

End If

教訓としては、VisualStudio が吐いたコードで DBNull チェックするときは DataRow.列名のプロパティ ではなく、DataRow.Is列名Null() メソッドを使わないといけないということですね。(もしくは DataRow("列名") Is DBNull.Value で判定する方法あり)