更新適用時の介入
レコードの更新 への移動
クライアント データセットで更新が適用される際は、データベース サーバーまたはソース データセットへの挿入データ、削除データ、変更データの書き込みを処理する方法をプロバイダ側で決定します。TClientDataSet を外部プロバイダ コンポーネントで使用する場合は、そのプロバイダのプロパティとイベントを使用して、更新の適用方法を制御することができます。これらについては、「クライアントの更新リクエストへの応答」を参照してください。
ただし、クライアント データセットがデータ アクセス メカニズムに関連付けられている場合のように、プロバイダが内部にある場合は、プロバイダのプロパティを設定したり、イベント ハンドラを用意することはできません。そのため、クライアント データセットでは、内部プロバイダによる更新の適用方法を制御できる 1 つのプロパティと 2 つのイベントを公開しています。
- UpdateMode では、更新の適用のためにプロバイダで生成される SQL 文でレコードの特定に使用されるフィールドを制御します。UpdateMode はプロバイダの UpdateMode プロパティと同一です。プロバイダの UpdateMode プロパティについての詳細は、「更新の適用方法への影響」を参照してください。
- OnGetTableName を使用すると、更新の適用先となるデータベース テーブルの名前をプロバイダに指定できます。これによりプロバイダは、CommandText で指定されたストアド プロシージャやクエリからデータベース テーブルを特定できない場合、更新用の SQL 文を生成できます。たとえば、単一テーブルの更新のみ必要な複数テーブル結合をクエリで実行する場合は、OnGetTableName イベントのハンドラを提供すると、内部プロバイダは更新を正しく適用できるようになります。OnGetTableName イベントのハンドラには、パラメータが 3 つあります。つまり、内部プロバイダ コンポーネント、データをサーバーから取得した内部データセット、生成された SQL で使用するテーブル名を返すパラメータです。
- BeforeUpdateRecord はデルタ パケット内のレコードごとに発生します。このイベントによって、レコードの挿入、削除、変更の直前に変更を行えるようになります。また、プロバイダで正しい SQL を生成できない場合(たとえば、複数のテーブルを更新する必要がある複数テーブル結合の場合など)には、更新を適用する独自の SQL 文を実行する手段にもなります。BeforeUpdateRecord イベントのハンドラには、パラメータが 5 つあります。つまり、内部プロバイダ コンポーネント、データをサーバーから取得した内部データセット、更新されようとしているレコード上に位置するデルタ パケット、更新が挿入、削除、変更のどれであるかを示す情報、イベント ハンドラで更新が実行されたかどうかを返すパラメータです。これらの使い方を以下のイベント ハンドラの例で示します。簡単にするため、この例では、SQL 文がフィールド値のみ必要なグローバル変数として使用できると仮定しています。
procedure TForm1.SimpleDataSet1BeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied Boolean); var SQL: string; Connection: TSQLConnection; begin Connection := (SourceDS as TSimpleDataSet).Connection; case UpdateKind of ukModify: begin { 1st dataset: update Fields[1], use Fields[0] in where clause } SQL := Format(UpdateStmt1, [DeltaDS.Fields[1].NewValue, DeltaDS.Fields[0].OldValue]); Connection.Execute(SQL, nil, nil); { 2nd dataset: update Fields[2], use Fields[3] in where clause } SQL := Format(UpdateStmt2, [DeltaDS.Fields[2].NewValue, DeltaDS.Fields[3].OldValue]); Connection.Execute(SQL, nil, nil); end; ukDelete: begin { 1st dataset: use Fields[0] in where clause } SQL := Format(DeleteStmt1, [DeltaDS.Fields[0].OldValue]); Connection.Execute(SQL, nil, nil); { 2nd dataset: use Fields[3] in where clause } SQL := Format(DeleteStmt2, [DeltaDS.Fields[3].OldValue]); Connection.Execute(SQL, nil, nil); end; ukInsert: begin { 1st dataset: values in Fields[0] and Fields[1] } SQL := Format(InsertStmt1, [DeltaDS.Fields[0].NewValue, DeltaDS.Fields[1].NewValue]); Connection.Execute(SQL, nil, nil); { 2nd dataset: values in Fields[2] and Fields[3] } SQL := Format(InsertStmt2, [DeltaDS.Fields[2].NewValue, DeltaDS.Fields[3].NewValue]); Connection.Execute(SQL, nil, nil); end; end; Applied := True; end;
void __fastcall TForm1::SimpleDataSet1BeforeUpdateRecord(TObject *Sender, TDataSet *SourceDS, TCustomClientDataSet *DeltaDS, TUpdateKind UpdateKind, bool &Applied) { TSQLConnection *pConn := (dynamic_cast<TSimpleDataSet *>(SourceDS)->Connection); char buffer[256]; switch (UpdateKind) case ukModify: // 1st dataset: update Fields[1], use Fields[0] in where clause sprintf(buffer, UpdateStmt1, DeltaDS->Fields->Fields[1]->NewValue, DeltaDS->Fields->Fields[0]->OldValue); pConn->Execute(buffer, NULL, NULL); // 2nd dataset: update Fields[2], use Fields[3] in where clause sprintf(buffer, UpdateStmt2, DeltaDS->Fields->Fields[2]->NewValue, DeltaDS->Fields->Fields[3]->OldValue); pConn->Execute(buffer, NULL, NULL); break; case ukDelete: // 1st dataset: use Fields[0] in where clause sprintf(buffer, DeleteStmt1, DeltaDS->Fields->Fields[0]->OldValue); pConn->Execute(buffer, NULL, NULL); // 2nd dataset: use Fields[3] in where clause sprintf(buffer, DeleteStmt2, DeltaDS->Fields->Fields[3]->OldValue); pConn->Execute(buffer, NULL, NULL); break; case ukInsert: // 1st dataset: values in Fields[0] and Fields[1] sprintf(buffer, UpdateStmt1, DeltaDS->Fields->Fields[0]->NewValue, DeltaDS->Fields->Fields[1]->NewValue); pConn->Execute(buffer, NULL, NULL); // 2nd dataset: values in Fields[2] and Fields[3] sprintf(buffer, UpdateStmt2, DeltaDS->Fields->Fields[2]->NewValue, DeltaDS->Fields->Fields[3]->NewValue); pConn->Execute(buffer, NULL, NULL); break; }