この特集のトップページへ
>
Chapter 5:ビジネスロジック層の構築
5.4.4 COMコンポーネントがトランザクションをサポートするには
いままで説明してきたように,トランザクションの状態はConsistentフラグがTrueであるかFalseであるかによって決まる。ここでは,COMコンポーネントからConsistentフラグをどのようにして設定するのかについて説明する。
●COM+にトランザクションの中止を通知する
まずは,トランザクションの中止をCOM+に通知する方法について説明する。トランザクションの中止をCOM+に通知するということは,ConsistentフラグをFalseに設定したのち,非アクティブ化するということである。
ConsistentフラグをFalseに設定するには,ObjectContextオブジェクトのDisableCommitメソッドもしくはSetAbortメソッドを呼び出す。
Dim objContext As ObjectContext Set objContext = GetObjectContext() objContext.DisableCommit もしくは objContext.SetAbort
DisableCommitメソッドはConsistentフラグをFalseに設定するだけだが,SetAbortメソッドはConsistentフラグをFalseに設定したうえで,さらにDoneフラグをTrueに設定する。すでに「5.3.1 ジャストインタイムアクティベータの基本」で説明したように,Doneフラグは非アクティブ化するためのフラグである。よって,SetAbortメソッドを呼び出した場合は,ConsistentフラグをFalseに設定したあと,COMオブジェクトを非アクティブ化することになる。
先に説明したように,トランザクションの状態を確認するのは,COMオブジェクトが非アクティブ化されたときのみである。よって,DisableCommitメソッドを呼び出した場合には,COM+に対してトランザクションの中止を通知するものの,実際にはまだトランザクションの中止が確定していない。DisableCommitメソッドを呼び出したときに通知されたトランザクションの中止が確定するのは,それ以降COMクライアントがCOMオブジェクトを手放したとき,あるいはルートオブジェクトが非アクティブ化されたときである。なお,DisableCommitメソッドで通知した中止命令は,次に説明するEnableCommitメソッドを使うことで取り消すことができる。
●COM+にトランザクションの成功を通知する
COM+においては,トランザクションの成功を通知する必要はない。なぜなら,COMオブジェクトが実体化されたときにはConsistentフラグがTrueに設定されるので,非アクティブ化されれば,トランザクションは成功することになるからである。しかし,逆にいうと,非アクティブ化されるまではトランザクションが決定しないことになり,都合が悪い。つまり,COMクライアントがCOMオブジェクトを手放すまで,トランザクションの状態が確定しなくなるのである。
そこで,トランザクションの状態をすぐに確定させたいときに備えて,ObjectContextオブジェクトにはSetCompleteメソッドが用意されている。一般的に,トランザクションの成功を確定させたければ,このメソッドを呼び出す。
Dim objContext As ObjectContext Set objContext = GetObjectContext() objContext.SetComplete
SetCompleteメソッドは,ConsistentフラグをTrueに設定し,さらにDoneフラグもTrueにする。結果,ジャストインタイムアクティベータの機能によって,このCOMオブジェクトが非アクティブ化されるので,即座にトランザクションの状態が確定することになる。
ConsistentフラグをTrueにするために,もう1つ,EnableCommitというメソッドも用意されている。
Dim objContext As ObjectContext Set objContext = GetObjectContext() objContext.EnableCommit
EnableCommitメソッドは,SetCompleteメソッドと違い,ConsistentフラグをTrueにするだけで,Doneフラグは操作しない。よって,COMオブジェクトを非アクティブ化するまでは,トランザクションの状態は確定しないのである。EnableCommitメソッドは,DisableCommitメソッドでConsistentフラグをFalseに設定したあと,これをTrueに戻したいときに利用する。
●DisableCommitメソッドの使い方
DisableCommitメソッドは,利用方法がわかりにくい側面もあろうと思われるので,補足的に説明しておく。
一般的にDisableCommitメソッドは,あるメソッドを呼び出した時点で別のメソッドを呼び出さないとトランザクションは成功しないような場合に用いる。たとえば,List 5-5に示す2つのメソッドを備えたCOMコンポーネント(COMオブジェクト)があるとする。
List 5-5のCOMコンポーネントは,COMクライアントから必ずfuncA,funcBの順で呼び出されるものとする。そして,funcBの呼び出しが終わるとコミットするものとする(その処理は,List 5-5の9行目に記してある)。
このCOMオブジェクトが,同じトランザクション範囲にある別のCOMオブジェクトから,funcA,funcBの順で呼び出されたとする。このとき正常に動作が完了すれば,funcBを呼び出した段階でトランザクションをコミットするであろう。では,何らかの理由でfuncAを呼び出したあと,funcBが呼び出されないまま,このCOMオブジェクトが非アクティブ化されてしまった場合にはどうなるのだろうか(このような事態は,COMオブジェクトが別のサーバーで動作している場合にはネットワークの障害によってしばしば発生し得る)。このとき,funcAはConsistentフラグを何も操作していないので,ConsistentフラグはTrueのままである。よって,トランザクションは成功するであろう。
しかし,場合によっては,このような処理は好ましくないこともある。たとえば,funcAのあとに必ずfuncBが呼び出されなかった場合には,トランザクションをアボートさせたいこともあるだろう。そのような場合には,funcAから戻るまえにDisableCommitメソッドを呼び出し,ConsistentフラグをFalseに設定する(List 5-6)。
こうしておけば,funcAが呼び出されたあとでfuncBが呼び出されるまえに非アクティブ化されてしまっても,DisableCommitメソッドの呼び出しでConsistentフラグをFalseに設定しているので,トランザクションはアボートされるようになる。もちろん,funcAが呼び出されたあとで正しくfuncBが呼び出されたとしても,List 5-5の9行目にあるSetCompleteメソッドの呼び出しによって,ConsistentフラグがTrueに設定される。そのため,トランザクションはコミットされることになる。
このようにDisableCommitメソッドは,トランザクションの状態が確定されるまでのあいだに複数のメソッドを呼び出す必要がある状況下において,後続するメソッドを呼び出すまえにCOMオブジェクトを非アクティブ化されてしまったときに,トランザクションをアボートする目的で使われる。
●トランザクション処理のまとめ
少々複雑な理論的な話が続いてしまったが,ここでトランザクション処理についてまとめておく。簡単にいってしまえば,あるCOMオブジェクトのトランザクション処理を完了させたければSetCompleteメソッドを呼び出し,中止させたければSetAbortメソッドを呼び出せばよい。
SetCompleteメソッドを呼び出した場合には,ConsistentフラグがTrueに設定されたあと,COMオブジェクトは非アクティブ化される。このとき,もしこのCOMオブジェクトがルートオブジェクトであれば,MS DTCに対してコミットの命令が発せられる。
SetAbortメソッドを呼び出した場合には,ConsistentフラグがFalseに設定されたあと,非アクティブ化される。これをCOM+が判断し,MS DTCに対してアボートの命令が発せられる。
極論をいってしまえば,COMオブジェクトがその仕事に成功したならばSetCompleteメソッドを,そうではなく失敗したならばSetAbortメソッドを呼び出せばよいのだ。DisableCommitメソッドやEnableCommitメソッドを使うと,より複雑な処理も実現できるが,別に無理して使う必要はない。ほとんどの場合,SetCompleteメソッドとSetAbortメソッドでだけで事足りる。
ただし,SetCompleteメソッドならびにSetAbortメソッドを呼び出したときには,そのCOMオブジェクトが非アクティブ化されるという点に注意してほしい。非アクティブ化されるということは,そのCOMオブジェクトが破棄され,次にCOMクライアントがCOMオブジェクトのメソッドを呼び出したときには,新しいCOMオブジェクトが実体化されるということである。つまり,SetCompleteメソッドおよびSetAbortメソッドを呼び出すまえにCOMオブジェクトに保存していた状態(COMオブジェクト内の変数が保持している値など)は,すべて失われるということになる。この動作を理解せずにCOMコンポーネントを実装すると,「ある変数に代入された値がいつのまにか初期化されている」などという不可解な状態に見舞われることになる。
くり返すようだが,トランザクションの状態を確定する要素は,Consistentフラグである。よって,データベースにアクセスしないCOMオブジェクトであっても,トランザクションに参加することはできる。また,Consistentフラグの状態にかかわらず,データベースアクセスそのものに失敗した場合(たとえば,データベースに接続できなかったり,書き込みに失敗したり,設定した制約に違反するデータを書き込もうとしたりした場合など)には,COM+側でなく,MS DTC側でアボート処理される。
Chapter 5-1 19/23 |