2.2.13 分散トランザクションのアプリケーションの作成
分散トランザクションのアプリケーションの開発には,.NET Frameworkが提供するSystem.Transactions名前空間内のAPIを使用します。
System.Transactionsでは,Transactionクラスに基づいた明示的なプログラミングモデルと,TransactionScopeクラスを使用した暗黙的なプログラミングモデルが提供されています。それぞれのプログラミングモデルを使用したConnector .NETのアプリケーション開発例を次に示します。
- 明示的なプログラミングモデルを使用したアプリケーション開発例
TP1ConnectionManager tcm = new TP1ConnectionManager(); // コネクションの取得 TP1Connection tc = tcm.GetConnection(); : // タイムアウトを5分に設定 TimeSpan timeout = new TimeSpan(0,5,0); using (CommittableTransaction ctrn = new CommittableTransaction(timeout)) { // トランザクションの開始 Transaction.Current = ctrn; // サービス要求の実行 bool ret = tc.Execute(); try { // トランザクションの完了 ctrn.Commit(); } catch (TransactionException exp) { TextBox1.Text = exp.ToString(); } } // コネクションの解放 tc.Dispose();
- 暗黙的なプログラミングモデルを使用したアプリケーション開発例
TP1ConnectionManager tcm = new TP1ConnectionManager(); // コネクションの取得 TP1Connection tc = tcm.GetConnection(); : // タイムアウトを5分に設定 TimeSpan timeout = new TimeSpan(0,5,0); // トランザクションの開始 using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, timeout)) { // サービス要求の実行 bool ret = tc.Execute(); // トランザクションの完了 ts.Complete(); } // コネクションの解放 tc.Dispose();
(1) コネクションとトランザクションの関係
コネクションとトランザクションには,次に示す関係があります。
-
トランザクション内でサービスを要求すると,そのコネクションが現在のスレッドコンテキストのトランザクションに参加します。
-
一つのコネクションを同時に複数のトランザクションに参加させることはできません。
-
複数のコネクションを一つのトランザクションに参加させることはできます。その場合,OpenTP1が管理するトランザクションブランチは複数になります。
-
トランザクションの操作が完了するまでコネクションは使用中のままとなります。
-
トランザクション内でTP1ConnectionクラスのDisposeメソッドを呼び出した場合は,アプリケーションからコネクションオブジェクトを解放するだけとなります。
-
分散トランザクションに参加したコネクションでは,ローカルトランザクションを開始することはできません。
-
分散トランザクションに参加したコネクションでTP1ConnectionクラスのBeginメソッドを呼び出すと,TP1ConnectorException例外が発生します。
-
コネクションが分散トランザクションに参加していない場合は,アプリケーションのトランザクション範囲内に記述されたTP1ConnectionクラスのBeginメソッドでもローカルトランザクションが開始されます。
暗黙的なプログラミングモデルを使用したアプリケーションの例とトランザクションの関係を次に示します。なお,明示的なプログラミングモデルの場合は,アプリケーションを次の表のように置き換えてください。
暗黙的なプログラミングモデル |
明示的なプログラミングモデル |
---|---|
TransactionScope(Required) |
CommittableTransactionオブジェクトをTransaction.Currentプロパティに設定 |
TransactionScope(RequiresNew) |
CommittableTransactionオブジェクトを新規にインスタンス化して,Transaction.Currentプロパティに設定 |
TransactionScope(Suppress) |
Transaction.Currentプロパティにnullを設定 |
Complete() |
Commit()またはRollback()の発行 |
(a) RPC実行時にトランザクションに参加する場合
RPC実行時にトランザクションに参加する場合の,アプリケーションの例とトランザクションの関係を次の図に示します。
|
コネクションを取得してサービスの要求を実行する前後で,トランザクションに参加します。
(b) トランザクションの終了前にコネクションを解放する場合
トランザクションの終了前にコネクションを解放する場合の,アプリケーションの例とトランザクションの関係を次の図に示します。
|
コネクションを解放してからトランザクションを終了します。トランザクションの開始後にコネクションを取得することもできます。
(c) トランザクション内でトランザクションとしないサービスを要求する場合
トランザクション内でトランザクションとしないサービスを要求する場合の,アプリケーションの例とトランザクションの関係を次の図に示します。
|
トランザクション内でトランザクションコンテキストの抑制を指定することで,サービスの要求をトランザクション外として扱うことができます。
また,トランザクション内でDCRPC_TPNOTRANフラグを指定してサービスを要求した場合も同様の動作となります。トランザクション内でDCRPC_TPNOTRANフラグを指定してサービスを要求した場合の,アプリケーションの例とトランザクションの関係を次の図に示します。
|
(d) トランザクション内で新しいトランザクションを作成する場合
トランザクション内で新しいトランザクションを作成する場合の,アプリケーションの例とトランザクションの関係を次の図に示します。
|
トランザクション内で新しいトランザクションを作成してサービスを要求する場合は,別に取得したコネクションを使用してください。一つのコネクションを同時に複数のトランザクションと関連づけた場合は,サービス要求時にTP1ConnectorExceptionが返されます。
(e) 同一のトランザクション内で複数のコネクションを使用する場合
同一のトランザクション内で複数のコネクションを使用する場合の,アプリケーションの例とトランザクションの関係を次の図に示します。
|
一つのトランザクション内で複数のコネクションを使用する場合は,複数のコネクションが同じトランザクションに参加します。
(f) WCF連携機能を使用した場合
WCF連携機能を使用した場合の,アプリケーションの例とトランザクションの関係を次の図に示します。
|
また,WCF連携機能を使用した場合でグローバルトランザクションのときの,アプリケーションの例とトランザクションの関係を次の図に示します。
|
WCF連携機能を使用する場合,TP1RpcClientクラスのCallメソッドを発行すると,内部でGetConnectionメソッド,Executeメソッド,およびDisposeメソッドが発行されます。しかし,トランザクション内の処理が完了するまでコネクションは使用中のままとなります。そのため,一つのトランザクション内で複数回TP1RpcClientクラスのCallメソッドを発行した場合は,複数のコネクションが生成されます。
- 注意事項
-
WCF連携機能を使用する場合,最大同時使用コネクション数(Connector .NET構成定義の<connection>要素のactive属性で指定)には,一つのトランザクション内で発行するTP1RpcClientクラスのCallメソッドの数以上を設定してください。
(2) トランザクションのタイムアウトの設定
System.Transactionsでは,トランザクションのタイムアウトを設定できます。次のどちらかの方法でトランザクションのタイムアウトを設定します。
なお,設定するトランザクションのタイムアウトの値には条件があります。条件については,「(c) 設定するトランザクションのタイムアウトの条件」を参照してください。
(a) アプリケーションから設定する場合
次に示す引数にタイムアウトを指定します。
- 明示的なプログラミングモデルを使用してアプリケーションを開発した場合
-
System.Transactions.CommittableTransactionクラスのコンストラクタの引数
- 暗黙的なプログラミングモデルを使用してアプリケーションを開発した場合
-
System.Transactions.TransactionScopeクラスのコンストラクタの引数
(b) コントロールパネルから設定する場合
コントロールパネルから設定する「トランザクション タイムアウト」の値は,「(a) アプリケーションから設定する場合」で設定しなかった場合のデフォルト値となります。
-
[コントロールパネル]−[管理ツール]−[コンポーネント サービス]を選択します。
[コンポーネント サービス]ダイアログを表示されます。
-
[コンソールルート]から,[コンピュータ]−[マイコンピュータ]を選択し,プロパティを開きます。
-
[オプション]タブの「トランザクション タイムアウト」の値を変更します。
(c) 設定するトランザクションのタイムアウトの条件
トランザクションのタイムアウトを設定する場合,CUP.NETおよびOpenTP1で設定する時間監視(問い合わせ間隔,メッセージの送受信など)の値を考慮して設定する必要があります。次の条件をすべて満たす値を設定してください。
-
トランザクションのタイムアウト(t0)>問い合わせ間隔(t1)
-
トランザクションのタイムアウト(t0)>メッセージの送受信(t2)
-
トランザクションのタイムアウト(t0)>トランザクションブランチの処理(t3)
-
トランザクションのタイムアウト(t0)<トランザクションブランチの処理完了(t6)
-
トランザクションのタイムアウト(t0)<トランザクションブランチの処理完了(t7)
トランザクションのタイムアウトの値が上記の条件を満たしていない場合,トランザクションの実行中にOpenTP1のサービス要求でタイムアウトが発生するおそれがあります。
トランザクションのタイムアウトの時間経過によるタイムアウトが発生した場合は,トランザクション内の処理が終了する前にロールバックが実行されることがあります。ロールバック完了後にトランザクション範囲内のTP1Connection.Executeメソッドなどが呼び出された場合,TP1ConnectorException例外が発生します。
CUP.NETおよびOpenTP1で設定する時間監視の監視区間を次の図に示します。また,時間監視の種類と設定方法を表2-5に示します。なお,図のt0〜t8は,表2-5の監視区間と対応しています。
|
監視区間 |
監視の種類 |
設定方法 |
|
---|---|---|---|
CUP.NETでの設定 |
OpenTP1での設定 |
||
t0 |
トランザクションのタイムアウト |
次のどちらかの方法で設定します。
|
− |
t1 |
問い合わせ間隔 |
|
|
t2 |
メッセージの送受信 |
次のどちらかの方法で設定します。
|
|
t3 |
トランザクションブランチの処理 |
|
|
t4 |
アイドル状態のトランザクションブランチ |
− |
|
t5 |
トランザクションブランチの処理 |
− |
|
サービス関数の処理 |
− |
|
|
t6 |
トランザクションブランチの処理完了 |
− |
|
t7 |
トランザクションブランチの処理完了 |
− |
|
t8 |
トランザクション同期点処理 |
− |
|
- (凡例)
-
−:設定できません。
(3) アプリケーションを開発する場合の注意事項
MSDTC連携機能を使用してアプリケーションを開発する場合は,次の点に注意してください。
-
構成定義の<distributedTransaction>要素のuse属性にはtrueを指定してください。falseを指定した場合,アプリケーションのトランザクション範囲内でOpenTP1にサービスを要求してもトランザクションには含まれません。
-
MSDTC連携機能を使用するアプリケーションで,スケジューラダイレクト機能およびネームサービスを使用したRPC要求をする場合は,必ずトランザクション範囲外で要求してください。トランザクション範囲内でスケジューラダイレクト機能およびネームサービスを使用したRPC要求をした場合,TP1ConnectorException例外が発生します。
-
TCP/IP通信機能を使用する場合は,トランザクション範囲内でのメッセージの送受信はできますが,トランザクションには含まれません。