2018-01-19

oo4oからADOへの変換 (7) Adapterクラスの作成(ADOでパラメータの名前によるバインドを可能にする)

移行方針について

oo4o から ADO へ移行する場合、大きく二つの方針が考えられると思います。
  1. 既存コードに手に入れず、oo4o のインタフェースを実装した ADO(ADO.NET)のラッパークラスを作成する。
  2. 全面的に ADO(ADO.NET)に書き換える。
まず、手っ取り早く (1) を検討したくなります。既存コードをそのまま利用できるのですから。しかし、今後もそのコードを継続して使用する場合、廃止された仕様に縛られ続けることにもなります。また、ADO とoo4o の仕様の差は大きく、 oo4o のインタフェースを完全に実装したラッパークラスの作成は困難です。
かといって、(2) の場合は書き換えに要する時間と費用の問題があります。oo4o と ADO の仕様の差は大きく書き換えも単純ではありません。(コンバータの作成を考えましたが、文法が大きく異なるため中途半端なものにならざるを得ません。)

では、どうするのか

移行に関係なく、データプロバイダの API を素のまま使わずデータベースアクセス用の共通クラスや関数を作成して手続きを単純化することは、よくある話ですし、望ましいことです。
その共通クラスの作成の際、oo4o の仕様を織り込むことで移行コストを抑えつつ、メンテナンス性も維持することを考えてみたいと思います。

ADO ラッパー(Adapter)クラスの作成

以下のような方針で ADO のラッパークラスを作成してみます。
  • 単一クラスとする。( Excel や Access のファイルに簡単に織り込めるのが望ましい。)
  • oo4o の OraSession、OraDatabase のインタフェースを極力実装する。
  • OraDynaset は対象外(ADO.Recordset に書き換える。)
  • Oracle のデータ型を使えるようにする。
  • 「名前によるバインド」を ADO でも可能にする。
クラス名は OraAdapter とします。
OraAdapter

使用例

OraAdapter クラスを使って Oracle® Objects for OLE開発者ガイドの OraParametersコレクション Addメソッド の例を書き換えてみます。
Sub Form_Load()

'Declare variables
'Dim OraSession As OraSession
'Dim OraDatabase As OraDatabase
  Dim OraDatabase As OraAdapter

'Create the OraSession Object.
'Set OraSession = CreateObject("OracleInProcServer.XOraSession")
  Set OraDatabase = New OraAdapter

'Create the OraDatabase Object.
'Set OraDatabase = OraSession.OpenDatabase("ExampleDb", "scott/tiger", 0&)
  OraDatabase.OpenDatabase "ExamleDb", "scott/tiger"

'Add EMPNO as an Input/Output parameter and set its initial value.
'OraDatabase.Parameters.Add "EMPNO", 7369, ORAPARM_INPUT
  OraDatabase.AddParameter "EMPNO", 7369, ORAPARM_INPUT
'OraDatabase.Parameters("EMPNO").serverType = ORATYPE_NUMBER
  OraDatabase.SetParameterServerType "EMPNO", ORATYPE_NUMBER
'または、OraDatabase.Parameters("EMPNO").Type = adNumeric

'Add ENAME as an Output parameter and set its initial value.
'OraDatabase.Parameters.Add "ENAME", 0, ORAPARM_OUTPUT
  OraDatabase.AddParameter "ENAME", 0, ORAPARM_OUTPUT
'OraDatabase.Parameters("ENAME").serverType = ORATYPE_VARCHAR2
  OraDatabase.SetParameterServerType "ENAME", ORATYPE_VARCHAR2
'または、OraDatabase.Parameters("ENAME").Type = adVarChar
'OraDatabase.Parameters("ENAME").Size = 255

'Add SAL as an Output parameter and set its initial value.
'OraDatabase.Parameters.Add "SAL", 0, ORAPARM_OUTPUT
  OraDatabase.AddParameter "SAL", 0, ORAPARM_OUTPUT
'OraDatabase.Parameters("SAL").serverType = ORATYPE_NUMBER
  OraDatabase.SetParameterServerType "SAL", ORATYPE_NUMBER
'または、OraDatabase.Parameters("SAL").serverType = adNumeric

'Execute the Stored Procedure Employee.GetEmpName to retrieve ENAME.
' This Stored Procedure can be found in the file ORAEXAMP.SQL.
  OraDatabase.ExecuteSQL ("Begin Employee.GetEmpName (:EMPNO, :ENAME); end;")
'Display the employee number and name.

'Execute the Stored Function Employee.GetSal to retrieve SAL.
' This Stored Function can be found in the file ORAEXAMP.SQL.
  OraDatabase.ExecuteSQL ("declare SAL number(7,2); Begin" & _
           ":SAL:=Employee.GetEmpSal (:EMPNO); end;")

'Display the employee name, number and salary.
  MsgBox "Employee " & OraDatabase.Parameters("ENAME").value & ", #" & _
          OraDatabase.Parameters("EMPNO").value & ",Salary=" & _
          OraDatabase.Parameters("SAL").value

'Remove the Parameters.
'OraDatabase.Parameters.Remove "EMPNO"
'OraDatabase.Parameters.Remove "ENAME"
'OraDatabase.Parameters.Remove "SAL"
  OraDatabase.ClearParameters
End Sub
そのまま書き換えた場合に比べ、大幅に単純化されていることが分かります。

補足

  • データプロバイダに OraOLEDB でなく MSDAORA を指定しても動きます。
  • OraAdapter.ParametersADODB.Parameter のコレクションです。
    したがって、OraDatabase.Parameters("EMPNO").serverType = ORATYPE_NUMBER は、
    OraDatabase.SetParameterServerType "EMPNO", ORATYPE_NUMBER
    ではなく
    OraDatabase.Parameters("EMPNO").Type = adNumeric
    に書き換えることも可能です。
  • CreateOraDynasetOraDynaset ではなく、ADODB.Recordset を返します。
    OraDynasetRecordset の違いについては、以下の記事も参考にしてください。
  • パラメータを変更してOraDynaset.Refresh をしている場合は、
OraAdapter.RefreshParameters
OraDynaset.Requery
に書き換えてください。

1 comment:

  1. 本当に助かりました。
    これは参考にさせていただきます。

    ReplyDelete