すぐ使えるADO.NET

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

本の紹介

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

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




【第11号】

 第11号(2004.7.23発行)
======================================================================
           ★★ VB.NETデータベースプログラミング奮闘記 ★★

----------------------------------------------------------------------
ADO.NETの基本的なプログラミングを中心に掲載します。
末永くご購読の程よろしくお願い申し上げます。

すぐ使えるADO.NET --> サンプルプログラム満載
                      http://park5.wakwak.com/‾weblab/
======================================================================
                          -----【目次】-----

1. VB.NETワンポイント:四捨五入
2. 部門単位で自動連番を生成するクラスの作成 2

----------------------------------------------------------------------
                ■■ VB.NETワンポイント:四捨五入 ■■

VB.NETでは、小数点以下(円未満)を四捨五入して、整数にする場合は、少し工
夫する必要があります。たとえば、MathクラスのRoundメソッドは、CInt関数
と同様に、最も近い整数に丸め、四捨五入になりません。

  System.Math.Round(2.5) --> 2

となり、中間値0.5は、偶数に丸められます。

正の整数を四捨五入する場合、+0.5を加えた後、小数点以下を切り捨てる方法
がありますが、私は、「FORTRAN入門改訂版」(培風館)を読んで、初めてこの方
法を知りました。VB.NETでは、次のようになります。

  Option Strict Offの場合:Int(四捨五入する数 + 0.5)
  Option Strict On の場合:CInt(Int(四捨五入する数 + 0.5))

今回は、正負を考慮しますので、正の数の時は、+0.5を加え、負の数の時は、
-0.5を加える必要があります。

0.5の加減は、System.MathクラスのSignメソッドを使います。このメソッドの
戻り値は、正の数の時、+1で、負数の時、-1になります。0の時は、0です。
四捨五入する数を8.45と-8.45とすると、

  System.Math.Sign(8.45)  --> +1
  System.Math.Sign(-8.45) --> -1

となります。よって、+0.5または、-0.5の加算は、Signメソッドを利用して、

  0.5 * System.Math.Sign(8.45)  --> +0.5 * +1 --> +0.5
  0.5 * System.Math.Sign(-8.45) --> -0.5 * -1 --> -0.5

です。その後、Fix関数を使って、小数点以下を切り捨てます。
(注:Int関数は、負の数の場合、四捨五入になりません。)

  Fix(8.45 + 0.5 * System.Math.Sign(8.45))   --> 8
  Fix(-8.45 + 0.5 * System.Math.Sign(-8.45)) --> -8

では、いくつか例を紹介します。以下の例では、
Option Strict Onとして、Imports System.Mathをコーディングしています。

  Dim dbl1 As Double = 120.5
  Dim dbl2 As Double
  Dim iNum As Integer

  dbl2 = Fix(dbl1 + 0.5 * Sign(dbl1))          ' --> 121.0
  iNum = CInt(Fix(dbl1 + 0.5 * Sign(dbl1)))    ' --> 121

  dbl1 = -120.4
  dbl2 = Fix(dbl1 + 0.5 * Sign(dbl1))          ' --> -120.0
  iNum = CInt(Fix(dbl1 + 0.5 * Sign(dbl1)))    ' --> -120

  Dim dec As Decimal = 2.49D
  iNum = CInt(Fix(dec + 0.5 * Sign(dec)))      ' --> 2

----------------------------------------------------------------------
         ■■ 部門単位で自動連番を生成するクラスの作成 2 ■■

前号の続きで、自動連番生成クラスclsSequenceNumを構築します。
自動連番生成テーブルは次のように定義しています。

key フィールド名   データ型    サイズ  値要求  空文字列の許可
----------------------------------------------------------------
◎ 部門コード  テキスト型    3 はい  いいえ
− 連番     数値型    整数型 はい  −
− 更新日時   日付/時刻型   − はい  −  --> 注:未使用

コンストラクタで、引数の部門コードをmBumonCodeに設定します。そして、
部門コードのレコードが連番生成テーブルに存在するかしないかを
existBumonメソッドで調べます。戻値がTrueならば、レコードが存在し、
Falseならば、レコードが存在しません。レコードが存在しないときは、
createSequenceNumメソッドを呼び出して、連番フィールドを0で初期化して、
連番生成テーブルに1レコード追加します。

  If Me.existBumon = False Then
    Me.createSequenceNum()
  End If

連番を取得するときは、getSequenceNumメソッドを呼出します。戻値は、文字
列で、取得した連番を1234とすれば、+1して、次のようになります。
  部門コード="001":戻値は、"00101235"
  部門コード="A01":戻値は、"A0101235"
  取得が失敗した時:戻値は、""(長さ0の文字列)

連番の編集は、String.Formatメソッドを使っています。詳細はこちらを参考
にして下さい。 http://park5.wakwak.com/‾weblab/refFormat.htm

取得した連番を+1して、レコードを更新するSQL文は、次のようにします。

 "UPDATE 連番生成テーブル SET 連番=@nextNum
                WHERE 部門コード = @bumonCode AND 連番=@nowNum"

ここで、@nextNumnには、取得した連番を+1した値を設定します。WHERE句の
@nowNumには、取得した連番の値を設定します。"AND 連番=@nowNum"は、念の
ため、他で連番が更新されていないかを確認するために追加しました。

連番生成テーブルを更新するため、ExecuteNonQueryメソッドを実行します。
戻り値は、更新したレコード数です。戻り値が1ならば、更新成功となります。
(0ならば、更新レコードなしで、2以上はありえません。)

  Dim count As Integer = oCommand.ExecuteNonQuery()
  If count = 1 Then
    '更新成功処理
  Else
    '更新失敗処理
  End If

それでは、コンストラクタとgetSequenceNumのソースリストを掲載します。

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

Public Class clsSequenceNum

  '------------------------ プロパティ ------------------------
  '部門コード
  Private mBumonCode As String

  '------------------------------------------------------------
  ' 機能:コンストラクタ
  ' 引数:in 部門コード
  '------------------------------------------------------------
  Sub New(ByVal parBumonCode As String)

    MyBase.New()
    Me.mBumonCode = parBumonCode

    '部門コードのレコードがなければ、1レコード追加
    If Me.existBumon = False Then
      Me.createSequenceNum()
    End If

  End Sub

  '------------------------------------------------------------
  ' 機能:連番生成テーブルから連番を取得する関数
  ' 引数:なし
  ' 戻値:8桁文字列ならば、取得成功
  '       ""(長さ0の文字列)ならば、取得失敗
  '------------------------------------------------------------
  Public Function getSequenceNum() As String

    Dim oConn As New OleDbConnection()
    Dim oCommand As New OleDbCommand()
    Dim oDataReader As OleDbDataReader
    Dim renban As Integer

    Try
      'DB接続文字列の設定
      '注:プロジェクトファイルホルダの下にあるbinホルダにMDBを置く
      oConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" + _
      " Data Source=" + Application.StartupPath + "¥sample.mdb"

      'コネクションの設定
      oCommand.Connection = oConn

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

      'SQL文の設定
      Const strSelect As String = _
      "SELECT 連番 FROM 連番生成テーブル WHERE 部門コード = @bumonCode"
      oCommand.CommandText = strSelect

      'SQL文パラメータの設定
      oCommand.Parameters.Add _
              (New OleDbParameter("@bumonCode", OleDbType.Char, 3))
      oCommand.Parameters("@bumonCode").Value = mBumonCode

      '取得するレコードが1件の時は、
      'パラメータにCommandBehavior.SingleRowをセット
      oDataReader = oCommand.ExecuteReader(CommandBehavior.SingleRow)
      If oDataReader.Read() Then
        '---------- レコードが取得できた時の処理 ---------
        '連番セット
        renban = CInt(oDataReader("連番"))

        'データリーダを閉じる
        If Not oDataReader Is Nothing Then
          oDataReader.Close()
        End If

        '連番を+1してレコードを更新
        Const strUpdate As String = "UPDATE 連番生成テーブル " + _
        "SET 連番=@nextNum " + _
        "WHERE 部門コード = @bumonCode AND 連番=@nowNum"

        'SQL文の設定
        oCommand.CommandText = strUpdate

        'SQL文パラメータの設定
        oCommand.Parameters.Clear()
        oCommand.Parameters.Add _
            (New OleDbParameter("@nextNum", OleDbType.Integer))
        oCommand.Parameters("@nextNum").Value = renban + 1
        oCommand.Parameters.Add _
            (New OleDbParameter("@bumonCode", OleDbType.Char, 3))
        oCommand.Parameters("@bumonCode").Value = mBumonCode
        oCommand.Parameters.Add _
            (New OleDbParameter("@nowNum", OleDbType.Integer))
        oCommand.Parameters("@nowNum").Value = renban

        '連番生成テーブル更新SQL文実行
        Dim count As Integer
        count = oCommand.ExecuteNonQuery()

        If count = 1 Then
          '部門コードと5桁連番を連結して8桁文字列を作成
          Dim strNum As String = _
          String.Format("{0,3:000}", mBumonCode) + _
          String.Format("{0,5:00000}", renban + 1)
          '戻り値に作成した8桁文字列をセットしてリターン
          Return strNum
        Else
          '更新処理エラー時
          Return ""
        End If
      Else
        'レコードが取得できなかった時
        Return ""
      End If

    Catch oExcept As Exception
      '例外が発生した時の処理
      Throw New Exception(oExcept.ToString)

    Finally
      'DB接続を閉じる
      If Not oConn Is Nothing Then
        oConn.Close()
      End If

    End Try

  End Function

  '以下次号以降に掲載します。

End Class

----------------------------------------------------------------------
            ■■ 次号予告 第12号(8月5日頃発行予定) ■■

1. VB.NETワンポイント
2. 部門単位で自動連番を生成するクラスの作成 3

======================================================================
VB.NET データベースプログラミング奮闘記    第11号(2004.7.23)
          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.