Delphiのデータベース接続で使用するTFDMemTableは、
通常はIBM i 等のデータベースと接続して
TFDQuery(またはTFDTable)と連携させて使用する機会が多いかと思います。
しかし、TFDMemTableは単独でもローカルデータベースとして活用可能です。
今回はその主な手法を紹介します。
※ IBM i 等のデータベースと接続する場合の手法は、以下の旧Tipsをご参照ください。
Delphi/400 Tips>入門>ClientDataSetの使用方法
(基本的な操作方法はTClientDataSetと同じです。並べ替えや絞り込みについてもこちら。)
①:CreateDataSet
CreateDataSetメソッドは、新しい空のクライアント データセットを作成します。
通常のIBM i などのDBと接続している場合は、
[QueryまたはTable] → [TFDMemTable](ロジックで転送)
という階層構造にするのが一般的ですが、
ローカルデータベースとしてTFDMemTableを使用する場合はこの階層構造を使用しません。
CreateDataSetメソッドを行うと、Openした際と同じようにActiveがTrueになります。
レコードは0件で、フィールド設定は「FieldDefs」または「Fields」プロパティに
あらかじめ設定しておいた情報が使用されます。
// 新しい空のクライアント データセットを作成
FDMemTable1.Close;
FDMemTable1.CreateDataSet;
②:EmptyDataSet
開いているTFDMemTableのレコードを全削除します。
EmptyDataSetメソッドを使うとFilterで非表示になっているレコードも含めて
全て初期化されるため、現在表示中のレコードだけを全削除したい場合は
以下のように1レコードずつ削除します。
// 1行ずつ全削除する場合
while (not FDMemTable1.IsEmpty) do
begin
FDMemTable1.Delete;
end;
EmptyDataSetメソッドは、IBM i との連携時にも
TFDMemTableの初期化目的で利用機会があるかと思います。
③:Append・Insert・Edit・Post・Cancel・Delete
こちらは、IBM i との連携時にも多用されているメソッドのため軽く説明のみ。
データセットと記載している箇所は、
TFDMemTable以外のデータセットでも共通の処理となります。
- Append:データセットの最終行より下に新規行を1行追加します。
- Insert:データセットの現在行の上に新規行を1行追加します。
- Edit:データセットの現在行を編集します。
- Post:Append・Insert・Editでの行の編集を確定します。
- Cancel:Append・Insert・Editでの行の編集を取りやめます。
- Delete:データセットの現在行を削除します。
④:First・Last・Next・Prior・RecNo・Locate
こちらも、IBM i との連携時にも多用されているメソッドやプロパティのため軽く説明のみ。
- First:データセットの最初のレコードに移動します。
- Last:データセットの最終のレコードに移動します。
- Next:データセットの1つ下のレコードに移動します。
- Prior:データセットの1つ上のレコードに移動します。
- RecNo:データセットの現在行のレコード番号を取得します。
また、指定した場合はその番号のレコードにジャンプします。 - Locate:データセット内の指定した条件に合致するレコードにジャンプします。
詳しくはこちらのTipsをご参照ください。
⑤:SaveToFile
ここからがTFDMemTableを単独でローカルデータベースとして扱う際の真骨頂です。
SaveToFileメソッドを呼び出すと、
現在のデータセットに格納されているデータを外部ファイルに出力(保存)します。
引数は ①保存ファイルのフルパス、②形式指定 となっています。
(②形式指定 を省略またはsfAutoに指定すると、拡張子から自動判別されます。)
<実装例>
// 専用バイナリ形式で保存する場合(デフォルト拡張子 *.fds,*.fdb,*.adb)
FDMemTable1.SaveToFile(SaveDialog1.FileName, sfBinary);
// 専用XML形式で保存する場合(デフォルト拡張子 *.xml)
FDMemTable1.SaveToFile(SaveDialog1.FileName, sfXML);
// 専用JSON形式で保存する場合(デフォルト拡張子 *.json)
FDMemTable1.SaveToFile(SaveDialog1.FileName, sfJSON);
<留意事項>
TFDMemTableで上記のSaveToFile(および次項のLoadFromFile)を
行うにあたっては、画面内に以下のコンポーネントを配置しておく必要があります。
- 専用バイナリ形式を使う場合:TFDStanStorageBinLink
- 専用XML形式を使う場合:TFDStanStorageXMLLink
- 専用JSON形式を使う場合:TFDStanStorageJSONLink
⑥:LoadFromFile
SaveToFileメソッドで保存した外部ファイルに格納されているデータは、
LoadFromFileメソッドで読み込むことができます。
引数は読み込むファイルのフルパスを指定します。
基本的には上記⑤でSaveToFileしたTFDMemTableのデータのみ対応しており、
他の一般的なXMLや、TClientDataSetでSaveToFileしたデータ等はエラーになります。
対応さえしていれば、他の画面やアプリケーションでも汎用的に使用可能です。
⑤⑥を組み合わせると、何万件もレコードがあるような
大きなデータでも高速で読み込み・出力が可能です。
大容量かつ、例えば年に1度といった更新頻度が非常に低いマスターファイルなどが
存在する場合に、都度IBM i ではなくファイルサーバーに保管するような運用が効果的です。
<実装例>
// 読み込み
FDMemTable1.LoadFromFile(OpenDialog1.FileName);
その他の注意事項
- フィールド設定について
- CreateDataSetする場合は、
上記①で記載のようにTFDMemTableのフィールド情報として
FieldDefsまたはFieldsをあらかじめ設定しておく必要があります。
ただし上記⑤⑥のようにLoadFromFileする場合は、
読み込んだファイルの情報を使用するため設定不要です。
- CreateDataSetする場合は、
- 計算や集計について
- ローカルデータベースとして使用する場合、
基本的にはデータフィールドのみの取り扱いとなります。(計算や集計は不向きです)
上記⑤のようにSaveToFileする場合も、計算項目や集計項目は保存対象から除外されます。
- ローカルデータベースとして使用する場合、
- 文字フィールドの扱いについて
- 文字列フィールド(TStringField)の構造が古いバージョンから変更されておらず
扱いがANSIになっています。 - そのため、
- AsStringはAnsiStringとして読み書きされます。
- フィールドのSizeプロパティもバイト数単位の計算になっています。
- TStringFieldにUnicode依存文字を入力してPostすると
「?」に化けてしまいます。(「鷗」や「€」や絵文字など)
- Unicode依存文字を使用する場合は、フィールド設計時に
TStringFieldではなくTWideStringFieldを使用して下さい。
- 文字列フィールド(TStringField)の構造が古いバージョンから変更されておらず
TClientDataSetを使用する場合
ご利用のDelphi/400のバージョンが古いなどの理由で
TFDMemTableコンポーネントが使用できない場合は、
TClientDataSetでも上記①~⑥の操作を実行することが可能です。
TFDMemTableを使用する場合との違いは主に以下のポイントとなります。
- [QueryまたはTable] → [TDataSetProvider] → [TClientDataSet]
という階層構造を使用しないため、「ProviderName」プロパティを空にします。
- SaveToFileを行う際のデータ形式(第2引数)は以下のように変わります。
- 専用バイナリ形式(dfBinary)
- 専用XML形式(dfXML)※化ける文字があるため非推奨
- 専用XML形式(UTF-8ベース)(dfXMLUTF8)
- ※TFDStanStorage~~Linkのような、
別コンポーネントを同画面に配置する必要はありません。
しかし、TClientDataSetを使用する都合上、
運用PCへの適用時にmidas.dllの配置、または
dprファイルのuses節にMidaslibが必要になります。
- 先述の通り、TFDMemTableをSaveToFileしたファイルとは互換性がありません。
関連リンク
- TFDMemTable – RAD Studio API Documentation(エンバカデロ公式Webヘルプ)
- TClientDataSet – RAD Studio API Documentation(エンバカデロ公式Webヘルプ)
- Delphi/400:ローカルキャッシュ活用術(過去のテクニカルレポートPDF)