.NETの各種データベース接続を簡単にする「DbProviderFactories」

自社のみで開発を行って、すべてコミットするのであれば、データベースは1つに統一できますが、連係先が別ベンダーだったりし、複数のデータベースへ接続する場合が出てきます。
そんなとき、毎回ソースを修正し、コンパイルするのは大変です。

そこで「DbProviderFactories」を使い、データベース接続部分をデータプロバイダーにより切り替え、それ以降の処理を変更しなくて良いようにしました。

今まで接続を行ったデータベースは「PostgreSQL」「MySQL(ODBC)」「Oracle(ODBC/Instant Client)」「Symfoware(ODBC)」「MS SQLServer」「DB2(ODBC)」です。

記載されている内容は、自身の責任において行ってください。この記事により不具合が生じても一切責任は負いません。

必要なライブラリ等は予めインストール、参照の追加を行っておいてください。

ソース

Imports System.Data.Common
Imports Npgsql
Imports System.Data.SqlClient
Imports System.Data.Odbc
Imports System.Data.OleDb

Public Class comSql
  Public DB_CON As DbConnection
  Public DB_DR As DbDataReader
  Public DB_TRN As DbTransaction
  Dim _NG As String = "999"
  Dim _EOF As String = "100"
  Dim _OK As String = "000"
  Public strErrMsg As String = ""
  Public strFieldType_(,) As String
  Dim provider As String = ""
  Dim host As String = ""
  Dim dbnm As String = ""
  Dim port As String = ""
  Dim user As String = ""
  Dim pass As String = ""

  ''' <summary>
  ''' コンストラクタ
  ''' </summary>
  ''' <param name="_provider">データプロバイダー</param>
  ''' <param name="_host">ホスト名、IP、ODBCデータソース名</param>
  ''' <param name="_port">ポート番号</param>
  ''' <param name="_dbNm">データベース名</param>
  ''' <param name="_user">ユーザー名</param>
  ''' <param name="_pass">パスワード</param>
  ''' <remarks></remarks>
  Public Sub New( _
    ByVal _provider As String, ByVal _host As String, ByVal _port As String, ByVal _dbNm As String, ByVal _user As String, ByVal _pass As String _
  )
    provider = _provider
    host = _host
    port = _port
    dbnm = _dbNm
    user = _user
    pass = _pass
  End Sub

  ''' <summary>
  ''' データベースへの接続
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function dbCon() As Short
    Dim connectionClassNm As String = ""    ' コネクションクラス名
    Dim connectionStr As String = ""        ' 接続文字列
    Dim factory As DbProviderFactory
    Select Case provider
      Case "pgsql"
        connectionClassNm = "Npgsql"
        connectionStr = "Host=" & host & ";Port=" & port & ";Database=" & dbnm & ";User Id= " & user & ";Password=" & pass & ";Preload Reader=true;CommandTimeout=60;Encoding=EUC_JP;"
        Exit Select
      Case "mssql"
        connectionClassNm = "System.Data.SqlClient"
        connectionStr = "server=" & host & "," & port & ";Initial Catalog=" & dbnm & ";User ID= " & user & ";Password=" & pass & ";MultipleActiveResultSets=True;"
        Exit Select
      Case "odbc"
        connectionClassNm = "System.Data.Odbc"
        connectionStr = "DSN=" & host & ";UID=" & user & ";PWD=" & pass & ";"
        Exit Select
      Case "oledb"
        connectionClassNm = "System.Data.OleDb"
        connectionStr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & dbnm & ";User ID=" & user & ";Password=" & pass & ";"
        Exit Select
      Case "oracle"
        connectionClassNm = "Oracle.DataAccess.Client"
        connectionStr = "user id=" & user & ";password=" & pass & ";data source=" & host & ";"
        Exit Select
    End Select
    Try
      factory = DbProviderFactories.GetFactory(connectionClassNm)
      DB_CON = factory.CreateConnection()
      DB_CON.ConnectionString = connectionStr
      DB_CON.Open()
      Return _OK
    Catch ex As Exception
      strErrMsg = ex.ToString()
      Return _NG
    End Try
  End Function

  ''' <summary>
  ''' セレクトする
  ''' </summary>
  ''' <param name="_sql"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function dbSelect(ByVal _sql) As Short
    Dim _cmd = DB_CON.CreateCommand
    _cmd.CommandText = _sql
    Try
      DB_DR = _cmd.ExecuteReader
      If (DB_DR.HasRows = False) Then
        Return _EOF
      Else
        Return _OK
      End If
    Catch ex As Exception
      strErrMsg = ex.ToString
      Return _NG
    End Try
  End Function

  ''' <summary>
  ''' 取得した結果から1行返す。
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function getRowStr() As String()
    Dim strTmp As String = ""
    Dim strResults As String() = Nothing
    Dim i As Integer = 0
    Dim j As Integer = 0
    strErrMsg = ""
    Try
      If (DB_DR.Read) Then
        ReDim strResults(DB_DR.FieldCount - 1)
        'カラム数分ループ
        For i = 0 To DB_DR.FieldCount - 1
          If (DB_DR.IsDBNull(i)) Then
            strResults(i) = ""
          Else
            strResults(i) = DB_DR.GetString(i)
          End If
        Next i
      End If
      If (strResults Is Nothing) Then DB_DR.Close()
      If (strResults Is Nothing) Then DB_CON.Close()
      Return strResults
    Catch ex As Exception
      strErrMsg &= ex.Message.ToString()
      Return Nothing
    End Try
  End Function

  ''' <summary>
  ''' 行のフィールド名、型を取得
  ''' </summary>
  ''' <param name="paramDR"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function getFieldType(ByVal paramDR As DbDataReader) As Short
    Dim i As Integer
    Try
      If (paramDR.HasRows = False) Then
        Return _EOF
      End If
      ReDim strFieldType_(paramDR.FieldCount - 1, 1)
      For i = 0 To (paramDR.FieldCount - 1)
        strFieldType_(i, 0) = paramDR.GetName(i)
        strFieldType_(i, 1) = paramDR.GetDataTypeName(i)
      Next i
      Return _OK
    Catch ex As Exception
      strErrMsg = ex.ToString
      Return _NG
    End Try
  End Function


  ''' <summary>
  ''' SQLを実行する
  ''' </summary>
  ''' <param name="_sql"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function sqlExec(ByVal _sql As String) As Short
    Dim _cmd = DB_CON.CreateCommand
    _cmd.CommandText = _sql
    Dim ResultCnt As Int32
    Try
      ResultCnt = _cmd.ExecuteNonQuery
      If (ResultCnt = 0) Then
        Return _EOF
      Else
        Return _OK
      End If
    Catch ex As Exception
      strErrMsg = ex.ToString
      Return _NG
    End Try
  End Function


  ''' <summary>
  ''' クライアントの文字コードをセットする
  ''' </summary>
  ''' <param name="_enc"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function setEnc(ByVal _enc As String) As Short
    Dim shtResult As Short
    Try
      shtResult = sqlExec("set client_encoding to '" & _enc & "'")
      Return shtResult
    Catch ex As Exception
      strErrMsg = ex.ToString
      Return _NG
    End Try
  End Function

  ''' <summary>
  ''' 接続を閉じる
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function dbClose() As Short
    DB_CON.Close()
    Return _OK
  End Function

  ''' <summary>
  ''' トランザクションの開始
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function begin() As Short
    DB_TRN = DB_CON.BeginTransaction()
    Return _OK
  End Function

  ''' <summary>
  ''' トランザクションのコミット
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function commit() As Short
    DB_TRN.Commit()
    Return _OK
  End Function

  ''' <summary>
  ''' トランザクションのロールバック
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function rollback() As Short
    DB_TRN.Rollback()
    Return _OK
  End Function

End Class

使い方

' インスタンス作成
Dim comdb As New comSql("pgsql", "localhost", "5432", "testdb", "user", "password")
' 接続
comdb.dbCon()
'クライアント文字列セット
comdb.setEnc("UTF-8")
' セレクト実行
comdb.dbSelect("select id , username from usertable;")
' 処理
Do
  strRow = comdb.getRowStr
  If (strRow Is Nothing) Then
    ' 処理終了
    Exit Do
  End If
  ' 処理
Loop
' 接続を閉じる
comsql.dbClose()

特記事項・雑感

バイナリ型、ラージオブジェクト型、XMLなんかが含まれている場合は、注意が必要です。

必要そうなライブラリとか

  1. Npgsql.dllダウンロード
  2. Oracle Instant ClientOracle社トップページ
スポンサーリンク
スポンサーリンク