公開データ モジュールでの状態情報のサポート

提供: RAD Studio
移動先: 案内検索

多層アプリケーションの作成:インデックス への移動

IAppServer インターフェイス(クライアント データセットがアプリケーション サーバー上のプロバイダと通信するために使用)は多くの場合、ステートレスです。 アプリケーションがステートレスであるとき、クライアントからの前の呼び出しで発生した事は何も "記憶" されません。 このステートレスの性質が便利なのは、トランザクション データ モジュールでデータベース接続をプールしている場合です。ユーザーのアプリケーション サーバーで、現在のレコードなどの保持情報に対して各データベース接続を区別する必要がないからです。 同様に、このステートレスの性質が、ジャストインタイム アクティベーション(オブジェクト プーリング)での場合と同様に、多くのクライアント間でリモート データ モジュールのインスタンスを共有しているときに重要です。 SOAP データ モジュールはステートレスであることが必要です。

ただし、アプリケーション サーバーへの呼び出し間で状態情報を維持することが必要な場合があります。 たとえば、インクリメンタル フェッチを使用してデータを要求するときは、アプリケーション サーバーのプロバイダは以前の呼び出しの情報(現在のレコード)を "記憶" する必要があります。

クライアント データセットが作成する IAppServer インターフェイス(AS_ApplyUpdates AS_ExecuteAS_GetParamsAS_GetRecords または AS_RowRequest)への呼び出しの前後で、カスタム状態情報を送信または受信できるイベントを受信します。 同様に、プロバイダがこれらのクライアント生成の呼び出しに応答する前後で、これらのプロバイダはカスタム状態情報を取得または送信できるイベントを受信します。 このメカニズムを使用すると、保持状態情報をクライアント アプリケーションとアプリケーション サーバー間で通信できます。アプリケーション サーバーがステートレスである場合でも可能です。

たとえば、次のパラメータ化クエリを表すデータセットを考えてみます。

SELECT * from CUSTOMER WHERE CUST_NO > :MinVal ORDER BY CUST_NO

ステートレスのアプリケーション サーバーでインクリメンタル フェッチを有効にするには、次の操作を実行します。

プロバイダがデータ パケットでレコード セットをパッケージ化するとき、パケットの最終レコードで CUST_NO 値を記憶します。

TRemoteDataModule1.DataSetProvider1GetData(Sender: TObject; DataSet: TCustomClientDataSet);
begin
  DataSet.Last; { move to the last record }
  with Sender as TDataSetProvider do
    Tag := DataSet.FieldValues['CUST_NO']; {save the value of CUST_NO }
end;
TRemoteDataModule1::DataSetProvider1GetData(TObject *Sender, TCustomClientDataSet *DataSet)
{
  DataSet->Last(); // 最後のレコードに移動
  TComponent *pProvider = dynamic_cast<TComponent *>(Sender);
  pProvider->Tag = DataSet->FieldValues["CUST_NO"];
}

このプロバイダではデータ パケットを送信した後に、この CUST_NO の最終値をクライアントに送信します。

TRemoteDataModule1.DataSetProvider1AfterGetRecords(Sender: TObject;
                   var OwnerData: OleVariant);
begin
  with Sender as TDataSetProvider do
    OwnerData := Tag; {send the last value of CUST_NO }
end;
TRemoteDataModule1::DataSetProvider1AfterGetRecords(TObject *Sender, OleVariant &OwnerData)
{
  TComponent *pProvider = dynamic_cast<TComponent *>(Sender);
  OwnerData = pProvider->Tag;
}

クライアントで、クライアント データセットは CUST_NO の最終値を保存します。

TDataModule1.ClientDataSet1AfterGetRecords(Sender: TObject; var OwnerData: OleVariant);
begin
  with Sender as TClientDataSet do
    Tag := OwnerData; {save the last value of CUST_NO }
end;
TDataModule1::ClientDataSet1AfterGetRecords(TObject *Sender, OleVariant &OwnerData)
{
  TComponent *pDS = dynamic_cast<TComponent *>(Sender);
  pDS->Tag = OwnerData;
}

データ パケットをフェッチする前に、クライアントは受信した、CUST_NO の最終値を送信します。

TDataModule1.ClientDataSet1BeforeGetRecords(Sender: TObject; var OwnerData: OleVariant);
begin
  with Sender as TClientDataSet do
  begin
    if not Active then Exit;
    OwnerData := Tag; { Send last value of CUST_NO to application server }
  end;
end;
TDataModule1::ClientDataSet1BeforeGetRecords(TObject *Sender, OleVariant &OwnerData)
{
  TClientDataSet *pDS = dynamic_cast<TClientDataSet *>(Sender);
  if (!pDS->Active)
    return;
  OwnerData = pDS->Tag;
}

最後に、サーバーで、プロバイダは、クエリの最小値として送信された、CUST_NO の最終値を使用します。

TRemoteDataModule1.DataSetProvider1BeforeGetRecords(Sender: TObject;
                    var OwnerData: OleVariant);
begin
  if not VarIsEmpty(OwnerData) then
    with Sender as TDataSetProvider do
      with DataSet as TSQLDataSet do
      begin
        Params.ParamValues['MinVal'] := OwnerData;
        Refresh; { force the query to reexecute }
    end;
end;
TRemoteDataModule1::DataSetProvider1BeforeGetRecords(TObject *Sender, OleVariant &OwnerData)
{
  if (!VarIsEmpty(OwnerData))
  {
    TDataSetProvider *pProv = dynamic_cast<TDataSetProvider *>(Sender);
    TSQLDataSet *pDS = (dynamic_cast<TSQLDataSet *>(pProv->DataSet);
    pDS->Params->ParamValues["MinVal"] = OwnerData;
    pDS->Refresh(); // クエリを強制的に再実行
  }
}

関連項目