TUIBDataSetをカスタマイズした。このカスタマイズしたコンポーネントを使って
TClientDataSet及びTDataSetProviderを使ってのデータ更新を試してみた。
以下、その備忘録
DBExpressドライバを使えば、フラットなテーブルや簡単なリンクテーブルであれば
自動的にデータ操作のSQLを作ってDBに書き込んでくれる。
しかし、複雑なJoin等でデータを表示する場合はDbExpressドライバを使っても
テーブルへの操作は自前で実施する必要がある。
また、FlameRobin、黒猫 SQL Studio、A5:SQL Mk-2のツールでデータ更新用の
SQLである程度自動で作成できるので 自前で実施してもそんなに手間ではないので
データの更新を手動で行う。
DataSetProviderで、データの更新を自分で実施する方法は、エンバカデロさんのヘルプ
に手順が書いてあるのでこれに従って更新処理を書いた。
その実装は、以下のとおり
フォームのUIBTransactionコンポーネントを配置し、UIBDatabaseコンポーネントを
接続する。また今回はテストなので、暗黙のトランザクションになるようの
コンポーネントを設定した。(下図)
UIBQueryコンポーネントを配置し上記のUIBTransactionオブジェクトに接続する。
DataSetProviderのUpdateModeを実際の処理に合わせて設定する。
(今回は、"upWhereChanged"に設定)
DataSetProviderのBeforeUpdateRecordイベントハンドラにDB更新の処理を
記述する。このとき、更新処理が終わったら、
Applied := true
とし、ClientDataSetのキャッシュの更新終了状態にする。
今回のテストで書いた処理は下のとおり、
- procedure TForm1.DataSetProvider1BeforeUpdateRecord(Sender: TObject;
- SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind;
- var Applied: Boolean);
- var
- i : Integer;
- SQL : String;
- ValueStr : String;
- NewStr : String;
- OldStr : String;
- //UIBDeltaDs : TUIBClientDataSet;
- begin
- //UIBDeltaDs := TUIBClientDataSet.Create(Self);
- //UIBDeltaDs := DeltaDS.CloneCursor();
- UIBQuery1.SQL.Clear;
- UIBQuery1.SQL.Add('UPDATE EMPLOYEE SET ' + #13#10);
- while not(DeltaDS.eof) do
- begin
- //DeltaDS
- SQL := '';
- for i := 0 to DeltaDS.FieldCount - 1 do
- begin
- //UIBDeltaDs.DataConvert(
- if not(VarIsEmpty(DeltaDS.Fields[i].NewValue)) then
- begin
- //UIBQuery1.SQL.Add
- NewStr := VarToStr(DeltaDS.Fields[i].NewValue);
- OldStr := IfThen(not(VarIsNull(DeltaDs.Fields[i].OldValue)), VarToStr(DeltaDS.Fields[i].OldValue));
- if CompareText(NewStr,OldStr) <> 0 Then
- begin
- if (DeltaDs.Fields[i].DataType = ftDatetime) then
- begin
- ValueStr := FormatDateTime(
- 'yyyy/mm/dd hh:nn:ss',
- VarToDateTime(DeltaDs.Fields[i].NewValue)
- );
- ValueStr := QuotedStr(ValueStr);
- end
- else
- begin
- ValueStr := VarToStr(DeltaDS.Fields[i].NewValue);
- if (DeltaDs.Fields[i].DataType = ftString)
- Or (DeltaDs.Fields[i].DataType = ftWideString)
- then
- begin
- ValueStr := QuotedStr(ValueStr);
- end
- end;
- end;
- SQL := SQL + ', ' + DeltaDS.Fields[i].FieldName + ' = ' + ValueStr + #13#10;
- ListBox1.Items.Add(DeltaDS.Fields[i].FieldName);
- ListBox1.Items.Add(NewStr);
- ListBox1.Items.Add(OldStr);
- end;
- end;
- if Length(Trim(SQL)) > 0 then
- begin
- Sql := RightStr(Sql,Length(Sql)-1);
- end;
- UIBQuery1.SQL.Add(SQL);
- UIBQuery1.SQL.Add('WHERE EMP_NO = ' + VarToStr(DeltaDS.FieldByName('EMP_NO').OldValue));
- Memo1.Lines.Assign(UIBQuery1.SQL);
- UIBQuery1.ExecSQL;
- DeltaDS.Next;
- end;
- Applied := true;
- //UIBDeltaDs.Free;
- end;
ここで、テーブルに対する操作は、UpdateKindで、変更対象のレコードは、DeltaDS
で取得できる。
あとは、適当なタイミングでClientDataSetのApplyUpdateメソッドをよびだせば、
データの更新ができる。(今回はボタンのクリックに割り当てた。)
以下、ソース例
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- //ClientDataSet1.Post;
- UIBClientDataSet1.ApplyUpdates(-1);
- end;