すぐ使えるADO.NET

【Visual BasicによるADO.NETデータベースプログラミング】

本の紹介

バックナンバー:VB.NETデータベースプログラミング

ADO.NETの基本的なプログラミングを中心に、すぐ使えるサンプルプログラム満載です。




【第38号】

 第38号(2006.3.3発行)
======================================================================
           ★★ VB.NETデータベースプログラミング奮闘記 ★★
----------------------------------------------------------------------
いつもご購読ありがとうございます。ADO.NETの基本的なプログラミングを中
心に掲載しますので、今後ともよろしくお願い申し上げます。

すぐ使えるADO.NET --> サンプルプログラム満載
                      http://park5.wakwak.com/‾weblab/
======================================================================
           ■■ VB.NETワンポイント:Optionalキーワード ■■

メソッドの引数の先頭にOptionalキーワードを付加して宣言すると、この引数
を指定しないで、メソッドを呼び出すことができます。引数を指定しない場合
には、引数の後に宣言された既定値が使用されます。Optionalキーワードを宣
言すると、それ以降の引数もすべてOptionalキーワードを付けて宣言しなけれ
ばなりません。

【例】正しい宣言
Public Function getRec(ByVal para1 As String, _
                       ByVal para2 As String, _
                       Optional ByVal para3 As String = "", _
                       Optional ByVal para4 As String = "abc") As DataTable

【例】誤った宣言
Public Function getRec(ByVal para1 As String, _
                       ByVal para2 As String, _
                       Optional ByVal para3 As String ="", _
                       ByVal para4 As String) As DataTable

ByVal para4 As String も、Optionalをつけて宣言する必要があります。

【例】誤った宣言
Public Function getRec(ByVal para1 As String, _
                       ByVal para2 As String, _
                       Optional ByVal para3 As String ="", _
                       Optional ByVal para4 As String) As DataTable

Optional ByVal para4 As String に既定値を指定する必要があります。

今回作成するメソッドでも、Optionalキーワードを使用します。

----------------------------------------------------------------------
     ■■ データベースアクセスクラスの汎用メソッドについて 7 ■■

今回は、引数に指定したキー値の範囲のレコードを取得する汎用的なメソッド
getRecordsOfRangeOfKeyを作成します。

◆引数のNothing(未設定)チェック
引数が未設定の場合、myDBIOException例外をスローします。

ただし、キーフィールド引数のparKeyfieldは、Optionalキーワードを付加し
て宣言しますので、引数の未設定チェックはしていません。

キーフィールド引数が既定値の空文字列の場合、引数のparTableNameのテーブ
ル名から、キーフィールド数を調べます。もし、単一主キーのテーブルならば、
GetOleDbSchemaTableメソッドでキーフィールド名を取得して、SQL文で使用し
ます。

キーフィールド引数が既定値の空文字列、かつ主キーが二つ以上ならば、
エラーとして、myDBIOException例外をスローします。

◆テーブル名チェック
引数のテーブル名がmTableNameListになければ、エラーとして、
myDBIOException例外をスローします。

◆SQL文の構築
WHERE句で、引数の範囲最小値と範囲最大値を利用して、SQL文を構築します。
今回使うSQL文は次のようになります。

 "SELECT * FROM  テーブル名 WHERE 主キーフィールド >= 範囲最小値 AND
  主キーフィールド <= 範囲最大値 ”

テーブル名は引数のparTableNameを、主キーフィールドには引数parKeyfield
を使います。引数主キーフィールドが未設定の場合には、GetOleDbSchemaTable
メソッドで取得した主キーフィールドを使います。範囲最小値と範囲最大値は
引数のparMinValueOfKeyとparMaxValueOfKeyを使います。

◆レコードの取得
データアダプタのFillメソッドを呼び出します。DataTable型の戻りオブジェ
クトの中に取得したレコードが格納されます。このオブジェクトをリターン
値にセットします。


【補足】引数の範囲最小値と範囲最大値のキー値の長さはチェックしていませ
ん。必要なら、たとえば、dataAdapter.Fill(retDataTable) の次行に、次の
コーディングを追加してください。

  '引数範囲最小値と範囲最大値の文字列の長さチェック
  If retDataTable.Rows.Count > 0 Then

    Dim keyItemLength As Integer
    keyItemLength = retDataTable.Rows(0)(parKeyfield).ToString.Length

    If Not parMinValueOfKey.Length = keyItemLength Then
      Throw New myDBIOException( _
            "エラー:引数範囲最小値の文字数が正しくありません")
    End If

    If Not parMaxValueOfKey.Length = keyItemLength Then
      Throw New myDBIOException( _
            "エラー:引数範囲最大値の文字数が正しくありません")
    End If

  End If


このメソッドでSELECT系は完了にします。次号では、テーブルに1レコードを
追加するメソッドをclsDBIOクラスに追加します。

--【プログラムソースリスト】------------------------------------------
Option Explicit On

Imports System.Data.OleDb
Imports System.Text.RegularExpressions

'----------------- << データベースアクセスクラス >> -----------------
Public Class clsDBIO

  '--------------------< メンバ:変数 >--------------------
  'コネクション
  Private mConn As OleDbConnection
  'コマンド
  Private mCommand As OleDbCommand
  'テーブル名コレクション
  Private mTableNameList As New Collection()

  '*******************************************************************
  ' 機能:コンストラクタ
  ' 引数:なし
  ' 履歴:2005.12.16 追加したFinallyブロックにmConn.Close()を移動
  '*******************************************************************
  Public Sub New()

    '第35号を参照願います。
    'http://park5.wakwak.com/‾weblab/mag035.html

  End Sub

  '*******************************************************************
  ' 機能:キー値のレコードの有無を調べるメソッド
  ' 引数:テーブル名、キー値
  ' 戻値:ある-->True、ない-->False
  ' 備考:キー値は英数字 "_" "-" で構成されていること
  '*******************************************************************
  Public Function existKeyRecord( _
    ByVal parTableName As String, ByVal parKeyValue As String) As Boolean

    '第33号を参照願います。
    'http://park5.wakwak.com/‾weblab/mag033.html

  End Function

  '*******************************************************************
  ' 機能:複数キー値のレコードの有無を調べるメソッド
  ' 引数:テーブル名、キーフィールド名配列、キー値配列
  ' 戻値:ある-->True、ない-->False
  ' 備考:キー値は英数字のみで構成されている
  '*******************************************************************
  Public Function existKeyRecord(ByVal parTableName As String, _
                                 ByVal parKeyfield() As String, _
                                 ByVal parKeyValue() As String) As Boolean

    '第34号を参照願います。
    'http://park5.wakwak.com/‾weblab/mag034.html

  End Function

  '*******************************************************************
  ' 機能:引数にテーブルと主キー値を指定してレコードを取得するメソッド
  ' 引数:String型 テーブル名
  ' 引数:String型 主キー値
  ' 戻値:DataTable型 取得したレコード
  '*******************************************************************
  Public Function getKeyRecord(ByVal parTableName As String, _
                               ByVal parKeyValue As String) As DataTable

    '第35号を参照願います。
    'http://park5.wakwak.com/‾weblab/mag035.html

  End Function

  '*******************************************************************
  ' 機能:複数キー値のレコードを取得するメソッド
  ' 引数:String型:テーブル名
  ' 引数:String型:主キーフィールド名配列
  ' 引数:String型:主キーフィールドに対応するキー値配列
  ' 戻値:DataTable型:取得したレコード情報
  ' 備考:キー値は英数字のみで構成されている
  '*******************************************************************
  Public Function getKeyRecord(ByVal parTableName As String, _
                               ByVal parKeyfields() As String, _
                               ByVal parKeyValues() As String) As DataTable

    '第36号を参照願います。
    'http://park5.wakwak.com/‾weblab/mag036.html

  End Function

  '*******************************************************************
  ' 機能:テーブルの全レコードを取得するメソッド
  ' 引数:String型:テーブル名
  ' 戻値:DataTable型:取得したレコード
  ' 備考:キー値は英数字のみで構成されている
  '*******************************************************************
  Public Function getAllRecords(ByVal parTableName As String) As DataTable

    '第37号を参照願います。
    'http://park5.wakwak.com/‾weblab/mailMagazine.html

  End Function

  '*******************************************************************
  ' 機能:引数に指定した主キー値の範囲のレコードを取得するメソッド
  ' 引数:String型-->テーブル名
  ' 引数:String型-->主キーの最少値
  ' 引数:String型-->主キーの最大値
  ' 引数:String型-->主キーフィールド名(指定しない場合は、既定値の空文字列)
  ' 戻値:DataTable型:取得したレコード
  ' 備考:主キー値は英数字のみで構成されている
  '*******************************************************************
  Public Function getRecordsOfRangeOfKey( _
                        ByVal parTableName As String, _
                        ByVal parMinValueOfKey As String, _
                        ByVal parMaxValueOfKey As String, _
                        Optional ByVal parKeyfield As String = "") _
                        As DataTable

    Dim retDataTable As New DataTable()                 'リターン値

    Try

      '★引数チェック
      If parTableName = Nothing Then
        Throw New myDBIOException("引数テーブル名未設定")
      End If
      If parMinValueOfKey Is Nothing Then
        Throw New myDBIOException("引数主キー範囲最小値未設定")
      End If
      If parMaxValueOfKey Is Nothing Then
        Throw New myDBIOException("引数主キー範囲最大値未設定")
      End If
      If parMinValueOfKey > parMaxValueOfKey Then
        Throw New myDBIOException _
        ("エラー:引数主キー範囲最小値が最大値より大きくなっています")
      End If

     'テーブル名チェック
      Dim tblName As String
      Dim existFlg As Boolean

      For Each tblName In mTableNameList
        If tblName = parTableName Then
          existFlg = True
          Exit For
        End If
      Next tblName

      If Not existFlg = True Then
        Throw New myDBIOException("テーブル名不正")
      End If

      'DB接続を開く
      mConn.Open()

      '主キーフィールドの取得及びエラーチェック
      Dim schemaTable As DataTable
      schemaTable = mConn.GetOleDbSchemaTable( _
                    OleDbSchemaGuid.Primary_Keys, _
                    New Object() {Nothing, Nothing, parTableName})

      If parKeyfield = "" Then
        If schemaTable.Rows.Count = 1 Then
          parKeyfield = schemaTable.Rows(0).Item(3).ToString
        Else
          Throw New myDBIOException("引数主キーフィールド未設定")
        End If
      Else
        Dim keyList As New Collection()
        Dim i As Integer

        For i = 0 To schemaTable.Rows.Count - 1
          keyList.Add(schemaTable.Rows(i).Item(3).ToString)
        Next i

        Dim keyName As String

        existFlg = False
        For Each keyName In keyList
          If keyName = parKeyfield Then
            existFlg = True
            Exit For
          End If
        Next keyName

        If Not existFlg = True Then
          Throw New myDBIOException("引数のキーフィールド名不正")
        End If

      End If

      mCommand.Parameters.Clear()

      'キー値チェック(注:キー値は英数字と_と-で構成されている場合)
      parMinValueOfKey = parMinValueOfKey.Trim()
      '英数字以外はエラー
      If Not Regex.IsMatch(parMinValueOfKey, "^[0-9a-zA-Z_¥-]+$") Then
        Throw New myDBIOException( _
              "エラー:引数キー範囲最小値が正しくありません")
      End If

      parMaxValueOfKey = parMaxValueOfKey.Trim()
      '英数字以外はエラー
      If Not Regex.IsMatch(parMaxValueOfKey, "^[0-9a-zA-Z_¥-]+$") Then
        Throw New myDBIOException( _
              "エラー:引数キー範囲最大値が正しくありません")
      End If


      '***** SQL文の引数設定 *****
      mCommand.Parameters.Add( _
      New OleDbParameter("@key1", OleDbType.Char))
      mCommand.Parameters.Add( _
      New OleDbParameter("@key2", OleDbType.Char))

      '----------< コマンドパラメータに値を設定 >----------
      mCommand.Parameters("@key1").Value = parMinValueOfKey
      mCommand.Parameters("@key2").Value = parMaxValueOfKey

      'SQL文設定
      Dim wherePhrase As String
      wherePhrase = " " + parKeyfield + ">= @key1 AND"
      wherePhrase += " " + parKeyfield + "<= @key2"
      mCommand.CommandText = _
      "SELECT * FROM " + parTableName + " WHERE" + wherePhrase

      'テーブルからレコード取得
      Dim dataAdapter As New OleDbDataAdapter()

      dataAdapter.SelectCommand = mCommand
      dataAdapter.Fill(retDataTable)

    Catch oExcept As myDBIOException
      Throw New myDBIOException(oExcept.Message)
    Catch oExcept As Exception
      Throw New Exception _
      ("clsDBIOのgetRecordsOfRangeOfKeyで例外発生" + oExcept.ToString)

    Finally
      'DB接続を閉じる
      If Not mConn Is Nothing Then
        If mConn.State = ConnectionState.Open Then
          mConn.Close()
        End If
      End If

    End Try

    '◆リターン
    Return retDataTable

  End Function

End Class

'--------------- << 独自エラーメッセージ用例外クラス >> --------------
Public Class myDBIOException
  Inherits ApplicationException

  Public Sub New(ByVal errorMessage As String)
    MyBase.New(errorMessage)
  End Sub

End Class

----------------------------------------------------------------------
              ■■ 次号予告 第39号(3月30日発行予定) ■■
1. VB.NETワンポイント
2. データベースアクセスクラスの汎用メソッドについて 8
======================================================================
VB.NET データベースプログラミング奮闘記
  発行者:ウェブ実験室(-----@-----)
          http://park5.wakwak.com/‾weblab/
----------------------------------------------------------------------
このメールマガジン(マガジンID: 0000128094)は、
インターネットの本屋さん『まぐまぐ』から配信されています。
  http://www.mag2.com/

【購読中止の方法】購読の中止は次のホームページからお願い致します。
  http://park5.wakwak.com/‾weblab/
  http://www.mag2.com/m/0000128094.htm
----------------------------------------------------------------------
このメールマガジン及び「すぐ使えるADO.NET」ホームページで公開している
ソースプログラム・データの利用により生じた損害等については、発行者は
一切責任を負いません。ソースプログラムの再利用は自由です。著作権は発行
者が所有します。
このメールマガジン及び「すぐ使えるADO.NET」ホームページに掲載されてい
る会社名・製品名等は、各社の登録商標または商標です。
======================================================================

Copyright© すぐ使えるADO.NET. All rights reserved.