初音 玲 HATSUNE, Akira
MTSとは何か?
"MTSとは何か?"という問いは、"トランザクションとは何か?"という問いに行き着くだろう。トランザクションというのは、ある業務を行なうためのまとまった単位だ。たとえば、銀行に貯金を下ろしにゆくとしよう。
- 用紙に口座番号および金額を書き、印を押す
- 窓口に提出する
- 用紙と通帳と引き換えに番号札を受け取る
- 口座及ぶ残高確認
- 現金を金庫から持ってくる
- 記帳
- 番号札と引き換えに現金と通帳を受け取る
がひとつのトランザクションだ。そして、この手順のどこかで不都合(残高不足または記入ミス)が発見されたときには、用紙の記入からやり直しになる。そのため、口座からは引き出されるけれども現金が手元に来ないなどということが起きない様になっている。
通常、RDBMSを使えば、このようなトランザクション処理は可能だ。しかし、ビジネスロジックをクライアント側から分離してRDBMSに実装しようとすると、ストアドプロシージャの開発言語として、Visual Basic以外の言語を習得しなければならない。また、ビジネスロジックで、メールなどを使う時にも、かなり面倒なことになる。
そこで登場するのが、ビジネスロジックを配置するサーバーを別途設けた3階層C/Sシステムという考え方だ(図1)。そして、このビジネスロジック層で、トランザクションの管理を一括して行なう目的で開発されたのが、MTS(開発コード:Viper)だ(図2)。なお、MTSに登録されたActiveX DLLをMTSオブジェクト、そのMTSオブジェクトを使うクライアントをベースクライアントと呼ぶ。
MTSを使うことにより、トランザクション管理以外にも、
- よく使うビジネスロジックをメモリ上にロードしたままにする
- クライアントからの同時接続数を制限する
というオブジェクトのプール機能が手に入り、限られたサーバー資源を有効に使うことができる。トランザクション処理以外のこれらの機能は、いわゆるORB(Object Request Broker)と呼ばれる類のソフトウェアが提供する機能とオーバーラップしている。もちろん、MTSをORBと呼ぶことを疑問視する向きもあるが、本格的なORBを導入するにしてもMTSで済ませるにしても、自家製のオブジェクト管理プログラムが必要ないということには変わりがない。MTSというと、その名称からトランザクション関係に目が行ってしまうが、MTSを使う本当の意味は、このオブジェクト管理関係の機能にあるのだ。
Win95にMTSを入れる意義は?
MTS 2.0からは、Windows NT 4.0だけではなく、Windows 95にもインストールすることができる。これは、MTSのクライアントモジュールをインストールできるという意味ではない。MTS自身をインストールできるという意味だ。このことは、"Windows 95をサーバー化する"という無謀なことをまたやっていると思われるかもしれないが(私もそう思った)、そのような目的でインストールできるようになったのではない。
95でMTSを使う目的は、クライアントプログラムの動作環境としてMTSを使い、トランザクション対応のシステムを簡単に構築できるようにすることを目指している。そのため、Windows 95上でMTSを使うときには、
- NT4.0からリモート管理できない
- MTSロールによるセキュリティはなし
- 配布モジュールが作れない
- MTSとVB-IDEの連携デバッグができない(図3)
というような制限がある。
図3:MTS for Win95の制限
また、MTSを使ったプログラムの開発プラットフォーム、またはMTSの管理クライアントとしてWindows 95を活用できるが、開発環境と実行環境を同一環境にするのは、システム開発の言わば鉄則のようなものであり、NT4.0上のMTSで稼動するプログラムをWindows 95/98上のMTSを使って開発およびテストすることは無意味であることを付け加えておく。
なお今回は、スタンドアロンMTSアプリケーションの作成を通して、MTSプログラミングの手法を探ってゆきたいと思う。
MTSの最初の使用例
MTSをインストールしたマシン上に開発環境を構築したときには、MTSアドイン機能を使うことができる。このアドイン機能は、Visual BasicプロジェクトでMTS配下のActiveX DLLを、互換性のあるサーバーとして指定し、このプロジェクトからMTSへの反映を手軽に行なえるようにするための機能だ。この機能を使うためには、ActiveX DLLをMTS配下にするため、いったんMTSに該当ActiveX DLLを登録しておく必要がある。
ActiveX DLLの作成
MTSオブジェクトは、DCOMを使ってベースオブジェクトと連携する。普通、このようなときは、ActiveX EXEを利用することになる。しかし、ベースオブジェクトと直接連携するのはMTS自身だ。MTSとMTSオブジェクトは、同一空間で動作することで高パフォーマンスを目指している。そのため、DCOMを使うとはいえ、ActiveX DLLの形式でMTSオブジェクトを作成することになる。
Object Controlインターフェイスの実装
ActiveX DLLが作成できたら、MTSのオブジェクトプール機能を使うためのObject Controlインターフェイスを実装する。
- MTSのタイプライブラリを参照設定
- MTSTransactionModeプロパティを設定(表1)
- クラスモジュールの先頭で Implements ObjectControl を宣言
- コンテクストオブジェクト変数を宣言
ObjectControlを実装すると、
- ObjectControl_CanBePoolメソッド
- ObjectControl_Activateメソッド
- ObjectControl_Deactivateメソッド
がクラスのメソッドに追加される。
表1:MTSTransactionModeプロパティ
プロパティ 概要 NotAnMtsObject (既定値)MTSをサポートしない NoTransactions トランザクションをサポートしない RequiresTransaction オブジェクトは常にトランザクション中で動作する。トランザクションが開始されていれば、そのトランザクションを配下で動作する。トランザクションが開始されていなかったら、新しいトランザクションを開始する UsesTransaction 新しいオブジェクトを生成するときに、トランザクションを継承する。トランザクションがなければ、トランザクションなしで動作する RequiresNewTransaction 新しいオブジェクトを生成するときに、常に、新しいトランザクションを自動的に開始する
ObjectControl_CanBePoolメソッド
MTSがオブジェクトをプールして良いかを判定するための値を返す(リスト2中の*1)。もし、Trueを返して、オブジェクトのプールを許すときは、ObjectControl_Deactivateメソッド内で変数の初期化などが必要だ。
ObjectControl_Activateメソッド
このメソッドは、ベースオブジェクトからMTSオブジェクトを使うときに、最初に呼び出されるメソッドだ。通常は、自コンテクストオブジェクトを変数に保存するような初期処理を記述する(リスト2中の*2)。
ObjectControl_Deactivateメソッド
ベースオブジェクトからMTSオブジェクトの使用が完了したときに、このメソッドが呼び出される。通常は、ObjectControl_Activateメソッドが呼び出されたときの状態へ復帰するための、変数初期化処理などを記述する。たとえば、コンテクストオブジェクトへの参照を解放するなどといった処理だ(リスト2中の*3)。
MTSで実行する
MTSオブジェクトは、MTSに登録するまでは、単なるActiveX DLLと同じだ。MTSに登録して初めて、MTSオブジェクトとして振る舞うことができる。通常、ActiveX DLLをMTSサーバーマシンにコピーする必要があるが、今回は、スタンドアロンMTSアプリケーションなので、Visual BasicでActiveX DLLにコンパイルしたら、すぐにMTSエクスプローラを起動して登録できる。
- [マイコンピュータ]→[インストールされたパッケージ]を選択し、[操作]-[新規作成]メニューから「パッケージウィザード」を起動する。
- 初めて登録するので、[空のパッケージの作成]を選択し、パッケージの名前を入力する。
- [インストールされたパッケージ]→[パッケージ名(ここではFirstMTS)]→[コンポーネント]を選択し、[操作]-[新規作成]メニューから「コンポーネントウィザード」を起動する。
- [新しいコンポーネントをインストールする]を選択し、「コンポーネントのインストール」を起動し、ActiveX DLLファイルのファイル名を追加する。
MTSオブジェクトの登録時に、発生する間違いとしては、「コンポーネントウィザード」で[既存のオブジェクトをインポートする]を選択してしまい、インターフェイスが表示されない形で登録してしまうことだ。これは一見正常に登録できたように見えるが、「トランザクションの統計」などに情報が表示されない。もし、コンポーネントをどのように設定したか不明なときは、きちんとインターフェイスが表示されているか確認するのが良いだろう(リスト1)。
このサンプルを動作させるときに、Windows 95のMTSを使うならば、ここで忘れてはいけないのは、MTSエクスプローラを立ち上げておくことだ。そうしないと、普通のActiveX DLLとしてMTSオブジェクトを使ってしまう。試しに、MTSエクスプローラを立ち上げている時といない時の、ベースクライアントの起動速度を比較してみてほしい。MTS起動直後では、明らかにMTSを立ち上げていた方が遅いはずだ。これは、ActiveX DLLの初期ローディングに関しては、MTSを経由した方が当然時間がかかるからである。
リスト1:インターフェイスが正しく表示されるかを確認する
Public prpError As String Public pstrName As String Public Property Get prpNameLen() As Long On Error GoTo errNameLen: ' エラーが発生するプロパティ prpNameLen = Len(pstrName) / 0 exitNameLen: On Error Resume Next Exit Property errNameLen: MsgBox Error$ prpError = Error$ Resume exitNameLen: End Property Public Sub mtdReverseName() Dim intCt As Integer Dim strNew As String For intCt = 1 To Len(pstrName) strNew = Mid$(pstrName, intCt, 1) & strNew Next pstrName = strNew End Sub
コンテクストとは?
MTSでトランザクションを扱うときは、コンテクストの理解が必要だ。MTSがActiveX DLLを使うとき、これと同時にコンテクストオブジェクトが自動的に生成される。このコンテクストオブジェクトこそ、MTSのセキュリティおよびトランザクションを管理するオブジェクトなのだ。よって、ActiveX DLLからさらに他のActiveX DLLを呼び出すときは、コンテクストオブジェクトを引き継いで、MTSの一括管理下に置けるようにする。そのための機能が、CreateInstanceメソッドだ。
CreateInstanceメソッド
コンテクストオブジェクトの正式名称は、ObjectContextオブジェクトだ。このオブジェクトのCreateInstanceメソッドを使うと、呼び出し元のActiveX DLLのコンテクスト情報を引き継いでオブジェクトを生成する。つまり、CreateObjectメソッドの代わりにCreateInstanceメソッドを使えばよい。
ステートレスとステートフル
きれいに設計されたメソッドは、どのような順番で呼び出しても、それぞれの機能を実行してくれる。つまり、メソッドの呼び出し順を気にしなくてもよい。このような状態をステートレスといい、MTSオブジェクトの理想的な姿と言える。たとえば、RDBMSに対する操作ならば、あるメソッドを呼び出せば、RDBMSの接続、検索、更新、切断まですべてを行なうようなものだ。
しかし、一般的には、もう少し低機能のメソッドを用意して、何回かメソッドを呼び出して、ビジネスロジックを完成させることが多いだろう。このような時に"常に同じオブジェクトの別メソッドを呼び出すことができるか?"ということが問題になってくる。これはMTSオブジェクトの管理はMTSに一任しているために、あらかじめ何か指定をしておかなければ、オブジェクトが破棄されてしまったり他の利用者から使われてしまって、仕方なく別オブジェクトを生成し、そのメソッドを呼び出すようなことになるかもしれないということだ。
そこで、MTSオブジェクトに状態を持たせて、その状態を保持している間は、いつも同じオブジェクトを利用者が利用できるようにする機能がMTSには存在する。このように状態を持った姿をステートレスに対して、ステートフルと呼ぶ。
トランザクション管理
MTSは、ステートフルを実現することは、トランザクションを管理することと等価だと考えている製品だ。よって、DAOまたはRDOのBeginTrans、CommitTranおよびRollBackメソッドに相当するMTSのメソッドを呼び出し、複数メソッドに渡るトランザクションを設定することでステートフルなMTSオブジェクトを作成する。
DisableCommitメソッド
MTSオブジェクトがステートフルであることを宣言し、さらに、SetComplateメソッドまたはSetAbortメソッドを実行するまでは、実際の更新を行なわないことも宣言する。
SetComplateメソッド
SetComplateメソッドは、MTSオブジェクトのすべての処理が正常に終了したことをMTSに通知するメソッドだ。このメソッドを発行すると、それまでの作業をすべて確定していく。なお、このメソッドを発行したあとに同じMTSオブジェクトを使おうと思っても、MTSは同じクラスの別オブジェクトを割り当てるかもしれない。
SetAbortメソッド
SetAbortメソッドは、MTSオブジェクトの作業を無効にしたいときに発行する。つまり、トランザクションのロールバックを行なう。このメソッドを発行したあとも、SetComplateメソッドと同様に、同じMTSオブジェクトを使おうと思っても、MTSは同じクラスの別オブジェクトを割り当てるかもしれない。
トランザクションの設定
MTSオブジェクトがトランザクションをサポートできるようにプログラムされていれば、MTSにもそのことがわかるようにしなければならない。それが、トランザクションの設定だ。MTSエクスプローラの[コンポーネント]から、該当オブジェクトの[プロパティ]を選択して[トランザクション]タブの内容を設定する(図4、表2)。通常、呼び出されるごとに別々のトランザクションとする、つまり、利用者ごとに別々に情報を管理することが大半であり、そのようなときは、[新しいトランザクションが必要]を選択する。
なお、図4は、Windows 95のMTSエクスプローラだが、NT上では、[セキュリティ]タブが追加表示され、MTSロールの設定も可能になる。
図4:トランザクションの設定 図5:MTSからRDBMSを使う ![]()
![]()
表2:MTSトランザクションの設定
トランザクションサポート 概要 トランザクションが必要 オブジェクトは常にトランザクション中で動作する。トランザクションが開始されていれば、そのトランザクションを配下で動作する。トランザクションが開始されていなかったら、新しいトランザクションを開始する 新しいトランザクションが必要 新しいオブジェクトを生成するときに、常に、新しいトランザクションを自動的に開始する トランザクションをサポートする 新しいオブジェクトを生成するときに、トランザクションを継承する。トランザクションがなければ、トランザクションなしで動作する トランザクションをサポートしない トランザクションをサポートするコードが含まれていない
MTS使用例
〜ODBC
MTSは、MTSオブジェクトとODBCの間に入って、Microsoft DTC(Distributed Transaction Coordinator:分散トランザクションコーディネータ)を使って、トランザクションを提供する(図5)。
このMicrosoft DTCは、元々はSQL Serverの一部としてリリースされたサービスであり、複数のSQL Server間の分散処理などを行なう目的で作られたマイクロソフト社の独自技術だ。
MS DTCと連携してMTSよりODBCを使うためには、ODBC3.0以降のバージョンが必要だ。ここで難しいのは、ODBC3.0というのは、ODBCドライバのバージョンではなく、ODBCのレベル(仕様)のバージョンであるということだ。よって、ODBCドライバのバージョンを見ただけでは、それがODBC3.0以降のODBCドライバか不明なことが多い。
このようにODBCドライバがどのレベルの仕様を満たしているかが重要なポイントではあるが、それ以外は、とくに注意を払わなくても普通にRDOまたはODBC Directを使って、MTSオブジェクトとしてプログラムすればよい。そして、RDOなどのトランザクション系メソッドの代わりに、MTSの3つのトランザクション系メソッドを使えば良いのだ。
MTS使用例
〜XAインターフェイス
Microsoft DTCは、実質的にSQL Server専用のものだ。このことは、MTSのトランザクション管理の対象RDBMSがSQL Serverしか存在しないということを意味していた。しかし、MTSは、2.0になってから、XAインターフェイスプロトコルをサポートしている。XAインターフェイスプロトコルとは、X/Open DTP(Distributed Transaction Processing)仕様で規定されたトランザクション用の双方向システムレベルインターフェイスだ。Oracle、Sybase、IBM DB2、Informixなどの代表的RDBMS製品はこの仕様に準拠しているので、Microsoft DTCをサポートしていなくても、ODBCを使って、MTSからトランザクション管理を行なうことができる。
適用できるOracleのバージョンは?
XAインターフェイスがMTSの新バージョンからサポートされたということは、それに絡んでくるソフトウェアコンポーネント(ODBCドライバなど)もある程度新しいものが必要だということだ。これは、マイクロソフト社の製品を使う上での鉄則だ。Oracleに接続するためのソフトウェアコンポーネントとそのバージョンを表3にまとめた。
ここで気が付くのは、相変わらずOracle 7までの対応であり、Oracle 8に対応していない点だ。Visual Basic 6.0付属のOLE DBプロバイダなども、同じようにOracle 7のみがターゲットだった。マイクロソフト社がOracle 8クライアントを作る能力がないとは思えないので、これは営業戦略的にOracle 8をターゲットから外しているように思える。これでは、"Oracle 8までサポートして高機能な他社製品を選択させるようなことはしたくない"のだと思われてもしかたがない。裏を返せば、SQL Server 7が機能的に見ればOracle 7.R7.3と同等だからということも影響しているようにも思える。
表3:MTS + Oracleのバージョン組み合わせ
製品 バージョン RDBMS Oracle8(ただしSQL*Net接続) Oracle7 R7.3.4以上 クライアント SQL*Net Client 2.3.4.0.0以上 OCI 7.3.4.0.0 XA73 7.3.3.2.0以上 ODBC MS ODBC Driver for Oracle 2.73.7283.1以上
適用するには?
- データベース管理者権限のあるユーザーでOracleにログオンする
- V$XATRANS$ビューを作成する(ORA_HOME \RDBMS73\ADMINにあるxaview.sqlを投入する)
- SELECT権限を与える
GRANT SELECT ON V$XATRANS$ TO PUBLIC
適用できたかを確認するには?
MTS2.0をインストールすると、TestOracleXaConfig.exeというDOSベースのテストプログラムも同時にインストールされる。このテストプログラムを実行することで、XAインターフェイスを介した構成をチェックすることができる
TestOracleXaConfig -U<uid> -P<Password> -S<データベース別名>
このテストさえ通過すれば、MS DTCを使ってSQL Serverと接続しているときのように、ODBCを経由してOracle 7と接続することが「仕様的には」できる。
確かにXAインターフェイスを使えば、ODBCを経由してMTSとOracle間でトランザクションが連携可能だ。しかし、ここには大きな問題が含まれている。"ODBC経由のOracle接続が実用に耐えられるか"という点である。
Visual Basic Magazineの特集でも、過去に何度かOracle用ODBCドライバの、バージョン間の相性問題などが取り上げられていたが、MTSだから、XAインターフェイスだからといって、その相性問題から逃れられる訳ではない。つまり、安定したODBCレベル3以上のOracle用ODBCドライバの入手が必要不可欠なのだ。そのためには、マイクロソフト社またはオラクル社が製品に添付してくるような中途半端なODBCドライバ(マイクロソフト社にしてもOracleと接続できなかったらSQL Serverを薦めればいいのだし、オラクル社にしてもODBCドライバではなく自社製のミドルウェアが存在する)ではなく、ODBCドライバそのものを売り物にしているような会社の製品を選択すべきだろう。
MTS使用例
〜Oracle Objects for OLE
まともなODBCドライバをそれなりの料金を払って別途購入する解決方法もあるが、ここでは他の方法も探ってみよう。
Visual BasicからOracleに接続する方法としては、Oracle Objects for OLEが選択されるようになってきた。Oracle Objects for OLEは、ActiveX DLLであり、CreateObjectを使ってオブジェクトを生成する。MTSオブジェクトからOracle Objects for OLEを使ってトランザクション管理ができるか確認してみる価値はある(リスト2)。
さて、サンプルを動作させた結果だが、結論から言えば、
[Select]→[Edit]→[Error]
としたときと、
[Select]→[Edit]→[Update]
としたときで、まったく同じように動作してしまう。つまり、Oracle Objects for OLEは、MTSのコンテクストオブジェクトを介して管理できないということになる。
こうなってくると、普通にOracle Objects for OLEを使うActiveX DLLを作成し、そのオブジェクト自体をプールさせたり管理したりする手段としてMTSを利用することになる。非常に残念だ。
今後の課題と展望
MTSの機能を調べてみると、オブジェクト管理(ORB)面での機能はある程度充実してきたが、トランザクション面での機能は、思ったほど強力ではないことが見えてきた。たとえばMTSで、実質トランザクション管理ができるのは、ODBC経由のRDBMS上のデータ操作だけなのだ。もちろん、XAインターフェイスという方向もあるが、Windowsの世界に対するトランザクション管理能力が決定的に不足している。Windows APIを使った処理までトランザクション処理の対象にする必要はないが、COMを介して連携しているようなオブジェクトに対する操作は、すべてトランザクションの対象として欲しいと思う。
また、日本語版NTに対して、SP4をあてて、MTS 2.0を利用しているときには解決済みだが、英語版NTを利用しているときには、既知の障害が存在する。解決方法は、SP5を待つか、QFEをマイクロソフト社(http://www.microsoft.com/japan/products/ntupdate/nt4sp3/j041091.htm)から入手するかいずれかだ。
NT Explorerのアクセス違反
MTSを実行中に、Windows NT Explorerなどにアクセス違反が発生することがある。マイクロソフト社によれば、これは、サーバープロセスをシャットダウン中に初期化されていないhWndスタック変数により、不正なWindowsメッセージを動作中のアプリケーションに送るためだそうだ。
セキュリティホールの可能性
これも日本語版SP4では解決済みの問題だが、ActiveX EXEを代理サーバーにロードしてActiveX DLLに見せかけ、MTSに登録することができる。このような特殊な状況では、誰でもMTSに設定した以外のロールを使うことができてしまうというものだ。
この2点は、くどいようだが英語版NT 4.0(SP4)を利用するときのみの問題だ。英語版のNTを利用することなどあまりないように思えるが、IMEのメモリリークなどを嫌がり英語版を使っている所も多いと聞く。確かにNT 4.0になってから、IMEなどがOSカーネルに近い位置に置かれてしまい、たとえばIMEを外そうと思っても、日本語版では不可能なのだ。そこで、英語版の登場ということになる。さらに、英語版だとSPをあてる時期も「日本語版SPが出たら」ということを指針とすることもできるように感じる。これは、日本語版SPなどでは、SPに対するQEFが今回のように当たっているときがあるからだ。
さて、ActiveX DLLであるOracle Objects for OLEならば、MTSから使ってもなにか面白いことができるのではないかと思い、書き始めたが、結果的に思っていたようなことはできなかった。こうなったらMTSのオブジェクトプール機能だけでもOracle Objects for OLEからしゃぶり尽くすようなプログラムを作りたくなってくる。次回、予告を変更して、もう一度MTS with oo4oについて考察したい。「MTSとRDBMSのいい関係〜リベンジ編」だ!
MTSクライアント作成時の注意点(まとめ)1.オブジェクトの生成 MTSオブジェクトからMTSオブジェクトを生成するときは、 CreateInstanceメソッドを使う。 2.Friendの制限 FriendはMTSオブジェクトでは使えないので、Publicに変更する。 3.ODBCドライバ ODBC経由でRDBMSにアクセスしているときは、ODBCドライ バがODBC3.0をサポートしている必要がある。 [稼動確認環境] Windows 95 4.00.950c Internet Explorer 4.0 4.72.3110.8 MTS 2.00.00.546 Visual Basic 6.0 (SP2) Oracle Objects for OLE 2.3.1 SQL*Net Client 2.3.4 Net8 Client 8.0.5 Windows NT 4.0 Server (OP1) MTS 2.00.00.546 Windows NT 4.0 Server (SP3) Oracle8 EE R8.0.5リスト2:MTSオブジェクトからoo4oを使えるか確認する
Option Explicit ' (1)Microsoft Transaction Server Type Libraryの参照設定 ' (2)MTSTransactionModeの設定 ' (3)ObjectControlインターフェイスの実装 Implements ObjectControl Private mobjCnt As ObjectContext Private moraSes As Object ' OO4Oとのセション Private moraDb As Object ' RDBMSとのセション Private moraDs As Object ' SELECT集合 Public Sub mtdSelect(rstrSQL As String) On Error GoTo errSelect: rstrSQL = "SELECT * FROM EMP WHERE EMPNO=7935" Set moraDs = moraDb.DbCreateDynaset(rstrSQL, 0&) exitSelect: On Error Resume Next Exit Sub errSelect: App.LogEvent Error$ Err.Raise vbObjectError End Sub Public Sub mtdEdit() On Error GoTo errEdit: moraDs.DbEdit If moraDs("ENAME").Value = "HATSUNE" Then moraDs("ENAME").Value = "AKIRA" Else moraDs("ENAME").Value = "HATSUNE" End If exitEdit: On Error Resume Next Exit Sub errEdit: App.LogEvent Error$ Err.Raise vbObjectError End Sub Public Sub mtdUpdate() On Error GoTo errUpdate: moraDs.DbUpdate Set moraDs = Nothing mobjCnt.SetComplete exitUpdate: On Error Resume Next Exit Sub errUpdate: App.LogEvent Error$ Err.Raise vbObjectError End Sub Public Sub mtdError() On Error GoTo errUpdate: moraDs.DbUpdate Set moraDs = Nothing mobjCnt.SetAbort exitUpdate: On Error Resume Next Exit Sub errUpdate: App.LogEvent Error$ Err.Raise vbObjectError End Sub Public Sub mtdLogon(rstrHost As String, rstrConn As String) On Error GoTo errLogon: Set moraDb = moraSes.Opendatabase (rstrHost, rstrConn, 0&) exitLogon: On Error Resume Next Exit Sub errLogon: App.LogEvent Error$ Err.Raise vbObjectError End Sub *2*1
Private Sub ObjectControl_Activate() On Error GoTo errActivate: Set mobjCnt = GetObjectContext mobjCnt.DisableCommit Set moraSes = mobjCnt.CreateInstance _ ("OracleInProcServer.XOraSession") exitActivate: On Error Resume Next: Exit Sub errActivate: App.LogEvent Error$ Err.Raise vbObjectError End Sub*3
Private Function ObjectControl_CanBePooled() As Boolean ObjectControl_CanBePooled = False End Function
Private Sub ObjectControl_Deactivate() On Error Resume Next Set moraDb = Nothing Set moraSes = Nothing Set mobjCnt = Nothing End Subサンプルプログラムのダウンロード --- mts01.lzh(26KB)