たにぐちBLOG

C#が好きでたまんない

  PASSJブログ :: ホーム :: 連絡をする :: RSS  :: ATOM :: Login
  31 投稿数 :: 0 ストーリー :: 56 コメント :: 10 トラックバック

過去の記事

カテゴリ

イメージギャラリ

谷口です

Visual Basic 6.0で、なるべくコードの変更を少なくして複数のデータベースに確実に対応できるようにする方法についてです。
方法は色々考えられると思いますが、ここではVBのインターフェース(Interface)継承を用いてみようと思います。オブジェクト指向を完全にサポートしていないVisual Basic 6.0ですが、やれるところまでやってみようというお話です。

使用するDBはSQL Server 2000とOracleです。
テーブルはOracleの、scottにあるempテーブルを用います。
これを、SQL server 2000にインポートしました。
※以下のソースコードはエラー処理などが省略してあり、完全ではありません。
このテーブルのレコードを保存するために、VO(Value Object)を用意します。


' ソースコード(clsEmpVo):クラスモジュール

' Private 変数
' 従業員番号
Private m_lngEmpNo As Long
' 従業員名
Private m_strEname As String

' 以下略

' プロパティ

Public Property Get EMPNO() As Long
    EMPNO = m_lngEmpNo
End Property

Public Property Let EMPNO(lngEmpNo As Long)
    m_lngEmpNo = lngEmpNo
End Property

Public Property Get Ename() As String
    Ename = m_strEname
End Property

Public Property Let Ename(strEname As String)
    m_strEname = strEname
End Property

' 以下略(フィールド分同じものを作ります)



次に、データアクセス用インターフェースクラスを定義します



' ソースコード(clsEmpDao)クラスモジュール

Public Function SelectEmp(lngEmpNo As Long) As Collection

End Function

Public Function InsertEmp(EmpVo As clsEmpVo) As Boolean

End Function

Public Function UpdateEmp(EmpVo As clsEmpVo) As Boolean

End Function


このクラスのメソッドの中身は実装しません。

次にこれをImplementsしたSQL Server用クラスを作成します。
(ADO接続用オブジェクトは定義済みとします)


' ソースコード(clsEmpSQLServerDao):クラスモジュール

Implements clsEmpDao

Public Function clsEmpDao_SelectEmp(lngEmpNo As Long) As Collection

    Dim cmd As New ADODB.Command
    Dim result As New Collection
    Dim rs As ADODB.Recordset
   
    ' Commandの設定
    With cmd
        .ActiveConnection = adoSQLServerCon
        .CommandText = "SELECT * FROM EMP WHERE EMPNO = ?"
        .CreateParameter , adInteger, adParamInput
        .Parameters(0).Value = lngEmpNo
    End With
   
    ' SQLを実行して結果セットを取得します
    Set rs = cmd.Execute

    ' Recordsetから、VOへ値を詰めます
    Do Until rs.EOF
        Dim EmpVo As clsEmpVo
        Set EmpVo = New clsEmpVo
        ' 修正2005/07/08
        ' ここで Dim EmpVo = New clsEmpVoとやると
        ' EmpVoが使いまわされ、同じ値になってしまう

        EmpVo.EMPNO = lngEmpNo
        EmpVo.Ename = nvl(rs.Fields("ENAME"), "")
        EmpVo.Job = nvl(rs.Fields("JOB"), "")
        EmpVo.Mgr = nvl(rs.Fields("MGR"), 0)
        EmpVo.HireDate = nvl(rs.Fields("HireDate"), 0)
        EmpVo.Sal = nvl(rs.Fields("SAL"), 0)
        EmpVo.Comm = nvl(rs.Fields("COMM"), 0)
        EmpVo.DeptNo = nvl(rs.Fields("DEPTNO"), 0)
        Call result.Add(EmpVo)
        rs.MoveNext
    Loop
   
    ' 後始末
    rs.Close
    Set rs = Nothing
    
    ' 戻り値(VOのコレクション)の設定
    Set clsEmpDao_SelectEmp = result
   
End Function

Public Function clsEmpDao_InsertEmp(EmpVo As clsEmpVo) As Boolean
    ' 省略
End Function

Public Function clsEmpDao_UpdateEmp(EmpVo As clsEmpVo) As Boolean
    ' 省略
End Function



ポイントは先頭のImplements clsEmpDaoと、メソッド名の前にアンダーバーを使いインターフェースクラス名をつけることです。インターフェースクラスで定義されているメソッドは全て実装する必要があります。

同じくOracle用を作成します。ここではoo4oを使用しています。


' ソースコード(clsEmpOracleDao):クラスモジュール

Implements clsEmpDao

Public Function clsEmpDao_SelectEmp(lngEmpNo As Long) As Collection
   
    Dim oraDynaset As Object
    Dim result As New Collection
   
    ' パラメータのキー(EMPNO)
    Const EMPNO As String = "EMPNO"
   
    ' パラメータの定義
    oraDatabase.Parameters.Add EMPNO, lngEmpNo, ORAPARM_INPUT
    oraDatabase.Parameters(EMPNO).serverType = ORATYPE_NUMBER
   
    ' Dynaset
    Set oraDynaset = oraDatabase.CreateDynaset("SELECT * FROM EMP WHERE EMPNO = :EMPNO", 0&)
   
    ' DynasetkaからVOへ値を詰めます 
    Do Until oraDynaset.EOF
        Dim EmpVo As clsEmpVo
        Set EmpVo = New clsEmpVo
        ' 修正2005/07/08
        ' ここで Dim EmpVo = New clsEmpVoとやると
        ' EmpVoが使いまわされ、同じ値になってしまう

        EmpVo.EMPNO = lngEmpNo
        EmpVo.Ename = nvl(oraDynaset.Fields("ENAME"), "")
        EmpVo.Job = nvl(oraDynaset.Fields("JOB"), "")
        EmpVo.Mgr = nvl(oraDynaset.Fields("MGR"), 0)
        EmpVo.HireDate = nvl(oraDynaset.Fields("HireDate"), 0)
        EmpVo.Sal = nvl(oraDynaset.Fields("SAL"), 0)
        EmpVo.Comm = nvl(oraDynaset.Fields("COMM"), 0)
        EmpVo.DeptNo = nvl(oraDynaset.Fields("DEPTNO"), 0)
        Call result.Add(EmpVo)
        oraDynaset.MoveNextn 1
    Loop
   
    ' 後始末
    oraDatabase.Parameters.Remove EMPNO
    oraDynaset.Close
    Set oraDynaset = Nothing
    
    ' 戻り値(VOのコレクション)の設定
    Set clsEmpDao_SelectEmp = result

End Function

Public Function clsEmpDao_InsertEmp(EmpVo As clsEmpVo) As Boolean
    ' 省略
End Function

Public Function clsEmpDao_UpdateEmp(EmpVo As clsEmpVo) As Boolean
    ' 省略
End Function



データベース変更時のコード変更を楽にするために次のようなクラスを作ります。
プログラム中でEmpDaoクラスを作成する時は必ずこのクラスを使用するようにします。そうすることにより使用するデータベースをここで一括管理できます(他にもDaoクラスを作った時は全てここに生成関数を作ります)。DB接続のためのオブジェクト(clsEmpSQLServerDaoのadoSQLServerConやclsEmpOracleDaoのoraDatabase)についてはここでは詳しく扱いませんが、clsEmpDaoにプロパティを追加し(Property Set)、わたしてやるのがよいかもしれません。この方法は、この投稿のASP版

http://blogs.sqlpassj.org/masatotaniguchi/archive/2005/07/09/12119.aspx

で扱ってみました。



' ソースコード(clsScottDaoFactory) :クラスモジュール

Public Function EmpDao() As clsEmpDao
    Dim Emp As clsEmpDao
    ' 変更の必要な箇所
    Set Emp = New clsEmpSQLServerDao
    ' Set Emp = New clsEmpOracleDao
    Set EmpDao = Emp
End Function

' 他のDaoクラスの例
Public Function DeptDao() As clsDeptDao
    ' 略
End Function




次はこれらのクラスの使用例です。


' ソースコード(Form1):フォームモジュール

Private Sub Command1_Click()

    Dim result As Collection
    Dim ScottDaoFactory As New clsScottDAOFactory
    Dim EmpDao As clsEmpDao
    Dim EmpVo As clsEmpVo
   
    Set EmpDao = ScottDaoFactory.EmpDao
    Set result = EmpDao.SelectEmp(7839)
   
    Set EmpVo = result.Item(1)
   
    Text1.Text = EmpVo.Ename

End Sub



従業員番号が'7839'のものを選択する簡単なコードですが、DBを変更する必要が出た時に加える修正は実装クラスさえ作成してあれば1行ですみます。InterfaceクラスclsEmpDaoは入れ物の役目をしていて、入れ物には「何をするか」の定義だけが書かれています。必要に応じて中身を入れ替えるという考え方です。
DBによる違いは全て実装クラスで吸収できます。
MDI子ウィンドウの管理など他にも応用例があります。
投稿日時 : 2005年6月10日 1:16

コメントを追加

# ASP(非ASP.NET)で、なるべくコードの変更を少なくして複数のデータベースに確実に対応できるようにする 2005/07/09 2:43 たにぐちBLOG
ASP(非ASP.NET)で、なるべくコードの変更を少なくして複数のデータベースに確実に対応できるようにする

# ASP(非ASP.NET)で、なるべくコードの変更を少なくして複数のデータベースに確実に対応できるようにする 2005/07/09 2:47 たにぐちBLOG
ASP(非ASP.NET)で、なるべくコードの変更を少なくして複数のデータベースに確実に対応できるようにする

コメント

タイトル:
名前:
Url:
コメント: