この特集のトップページへ
Chapter 6:ビジネスロジックの設計



6.2.1 新規顧客の登録
●データベース接続文字列を動的に設定できるようにする
 以上で,DataObj.CustomerコンポーネントのAddRecordメソッドは完成する。実際,DataObj.Customerコンポーネントを実体化し,登録したい顧客情報を引数として引き渡してAddRecordメソッドを呼び出せば,顧客情報テーブルに新しいレコードが追加される(ただし,DataObj.CustomerコンポーネントはCOM+の機能を使っているため,[コンポーネントサービス]管理ツールを使ってCOM+として登録しないと正しく動作しない。登録方法については,すぐあとで説明する)。

 しかし,List 6-2で示した実装は,汎用性という点ではあまり好ましくない。なぜなら,データベース接続文字列を“Driver=SQL Server;Server=(local);UID=sa;Database=businesssampleDB;”に固定してしまっているためである(List 6-2の2行目)。より汎用性を高めるため,データベースの接続文字列はプログラム内で固定した値とせずに,管理者が決められるようにするのが望ましい。そこで,「5.7 コンストラクタ文字列」で説明したコンストラクタ文字列の機能を利用し,管理者がコンポーネントのプロパティとしてデータベース接続文字列を指定できるようにプログラムを修正する(Fig.6-10)。

Fig.6-10 コンストラクタ文字列の設定
fig6_10

 そのためにはまず,List 6-2の2行目を次のように書き換え,g_DBConnectionを定数(Const)ではなく変数とする。

  2: Dim g_DBConnection As String

 そして,コンストラクタ文字列を取得できるよう,DataObj.CustomerコンポーネントにIObjectConstructインタフェースを実装する。IObjectConstructインタフェースを実装するためには,次の行をCustomerクラスモジュールの先頭に追加する。

Implements IObjectConstruct

 さらに,IObjectConstructインタフェースのConstructメソッドが呼び出されたときに,管理者がコンポーネント管理ツールで設定したコンストラクタ文字列をg_DBConnection変数に保存するため,List 6-6に示すIObjectConstruct_Constructプロシージャを追加する。

 List 6-6の3行目では,管理者が設定したコンストラクタ文字列を取得し,g_DBConnection変数に代入している。List 6-2の92行目にあるAddRecordメソッドの処理内で,データベースを開くときにg_DBConnection変数の内容をデータベース接続文字列として使っている。そのため,結果として管理者が設定したコンストラクタ文字列をデータベース接続文字列として利用することになる。

 以上でコンストラクタ文字列をデータベース接続文字列として使うという目的が達せられたわけである。しかし,もし管理者がコンポーネント管理ツールでCOMコンポーネントのプロパティの[アクティブ化]ページで[オブジェクトの構築を有効にする]にチェックを付けなかったとすると,IObjectConstruct_Constructプロシージャは呼び出されない。つまり,g_DBConnection変数は初期化されないという状態になってしまい,好ましくない。

 そこで,[オブジェクトの構築を有効にする]にチェックが付けられていなかった場合には,“Driver=SQL Server;Server=(local);UID=sa;Database=businesssampleDB;”という文字列をg_DBConnection変数に代入することにする。そうしておけば,[オブジェクトの構築を有効にする]にチェックが付けられていなかった場合には,ローカルコンピュータのbusinesssampleDBデータベースに接続して利用するという意味になる。

 このように実装するには,DataObj.CustomerコンポーネントにObjectControlインタフェースを実装し,COMオブジェクトがアクティブ化されるときに呼び出されるActivateメソッドを利用すればよい(「5.3.3 ジャストインタイムアクティベータとイベント」を参照)。

 そこでまず,DataObj.CustomerコンポーネントにObjectControlインタフェースを実装するため,Customerクラスモジュールの先頭に次の行を加える。

Implements ObjectControl

 そして,ObjectControlインタフェースに備わるActivateメソッド,Deactivateメソッド,CanBePooledメソッドをCustomerクラスモジュールに追加する(List 6-7)。

 List 6-7の1〜7行目のObjectControl_Activateプロシージャが,COMオブジェクトがアクティブ化されるときに呼び出されるプロシージャである。4行目では,g_DBConnection変数の値が空文字でないかどうかを調べ,空文字であったならば,g_DBConnection変数に“Driver=SQL Server;Server=(local);UID=sa;Database=businesssampleDB;”という文字列を代入している。

 なお,4行目のg_DBConnection変数が空文字であるかどうかのチェックを省いてはならない。なぜなら,List 6-6に示したIObjectConstruct_Constructプロシージャが呼び出されたあとで,ObjectControl_Activateプロシージャが呼び出されるからである。もし4行目の空文字であるかどうかのチェックを省いたならば,IObjectConstruct_Constructプロシージャで格納したg_DBConnection変数の内容は,常にList 6-7の5行目で上書きされてしまうことになる。

 以上の実装によって,もし管理者が[オブジェクトの構築を有効にする]にチェックを付けていない場合には“Driver=SQL Server;Server=(local);UID=sa;Database=businesssampleDB;”という文字列をデータベース接続文字列として使い,チェックが付いていた場合には管理者が設定したコンストラクタ文字列をデータベース接続文字列として使う,という仕組みが備わったことになる。

注意 COMコンポーネントのプロパティの[アクティブ化]ページにおいて,[オブジェクトの構築を有効にする]にチェックを付けたものの,[コンストラクタ文字列]に何も入力しなかった場合には,COMコンポーネントの実体化に失敗することを筆者は確認した(具体的には,「以下のコンポーネントが構築のために構成されていますが,IObjectConstruct::Construct()メソッドに失敗したか,またはコンポーネントがIObjectConstructをサポートしていません」というエラーが発生する)。不思議なことに,[コンストラクタ文字列]に何か文字列を入力したのち,その文字列を削除した場合には問題は生じない。この問題は,実装したConstructメソッドが呼び出されるまえに発生してしまうため,プログラム的に回避することはできない。この現象は,Microsoft社のサポートページのアーティクルID「Q239879」で報告されている。

prevpg.gif Chapter 6 9/92 nextpg.gif