Table of Contents
インメモリデータセットの活用
本ブログでは、Delphi / C++Builderをある程度使用したことのある方をを対象として、FireDACの基本的な利用方法を解説していきます。
第5回のテーマ
- インメモリデータセットの概要
- 旧バージョンのプロジェクトでTClientDataSetを利用している場合の注意点
- TClientDataSetのデータをTFDMemTableへ移行するアプリケーション作成の演習
第4回までで、FireDACの基本的な使い方を習得できたと思います。今回は、少し応用的な内容へと進んでいきましょう。今回のテーマは、「インメモリデータセット」です。
インメモリデータセットは、メモリ上に展開されるデータベース非依存のデータセットです。FireDACのデータセットについては、第3回で紹介しました。TFDQueryやTFDTableなどのデータセットは、TFDConnectionによって接続するデータベース情報に紐付いたデータを扱うことが前提でしたが、インメモリデータセットは、データベースに依存せずメモリ上に保持されます。
インメモリデータセットを用いれば、キャッシュデータの保持や永続化を必要としない一時的なデータ保持などを効率的に実装できます。これはFireDACの強力な特長のひとつです。
今回の記事では、インメモリデータセットの概要と、それに併せてDelphi / C++Builderの古いバージョンでTClientDataSetを利用しているプロジェクトを移行する際の注意点について解説します。
インメモリデータセットの概要
インメモリデータセットとは、クライアントPCのメモリ上に展開されるデータセットで、FireDACでは「TFDMemTable」というコンポーネントとして提供されており、以下の特徴を持っています。
メモリ内にデータを保持
TFDMemTableのデータは、全てメモリ上で扱うことができるため高速なデータ操作が可能です。ただし、そのデータは、全てメモリ内に保持されますので、通常のデータセットとは異なり、クローズすると消失します。なお、TFDMemTableには、XML/BIN/JSON形式ファイルのインポート/エクスポート機能が用意されており、これらの形式でのデータ保管や読み込みが可能です。
データベース非依存
TFDQuery やTFDTableなどのデータセットでは、必ずデータベースへ接続する必要がありましたが、TFDMemTableではデータベースへの接続は必須ではありません。データベース非依存であるローカルのデータセットとして扱えます。
TClientDataSetと類似した機能
Delphi/C++Builderでは、非常に古いバージョンから「TClientDataSet」という名前のインメモリデータセットが提供されていました。TFDMemTableは、このTClientDataSetと類似する機能を持っているため、同じような使い方ができます。
TFDMemTableを利用するメリットは、ローカルDBのように振る舞えることです。
業務によっては、ネットワーク接続できない状況であってもシステムへのデータの入出力操作を中断できないケースがあるでしょう。このような場合、何らかの形で操作が継続できる仕組みを用意する必要があります。
例えば、ネットワーク接続した状態でリモート上のデータセンターから必要なデータを取得したら、一時的にキャッシュ目的でローカルデータセット(TFDMemTable)へため込みます。ネットワーク接続が失われたとしても、後でサーバーのデータと同期を取るような仕組みがあれば、操作を止めること無く業務を遂行することができるでしょう。
なおFireDACは、SQLiteやIBLiteといったローカルDBのデータアクセスにも対応しているため、ローカルデータセットではなく、ローカルDBへキャッシュする選択肢もあります。
リアルタイムのデータ同期を必要とするシステムには不向きですが、ローカルデータセットを活用することで、必要以上のリモートDBアクセスが発生しないため、ネットワークのトラフィックを減らすことができます。さらに、クライアントのメモリ上でデータを操作するため、処理のレスポンス性を向上させるメリットがあります。
旧バージョンのプロジェクトでTClientDataSetを利用している場合の注意点
次に、旧バージョンのDelphi/C++Builderで、TClientDataSetを利用している既存プロジェクトを移行する際の注意点について解説しましょう。
例えば、BDEやdbExpressなどのDBコンポーネントをFireDACへ置き換える場合、FireDACのデータセットとTClientDataSet-TDataSetProviderの組み合わせで引き続き利用するケースでは、従来の動作と異なることがあるという事例が報告されています。
FireDACに移行する場合、古いアーキテクチャであるTClientDataSetとTDataSetProviderを用いるのではなく、同じ新しいアーキテクチャ上に構築された代替機能であるTFDMemTableを用いるべきでしょう。
以下は、FireDACコンポーネントへ置き換えのためのいくつかの指針です。
FireDACでは、TClientDataSetとTDataSetProviderは不要
dbGOやdbExpressなどのDBコンポーネントは、単方向データセットしかサポートしていないので、TDBGridなどのグリッドコントロールにデータを表示させるためにTCientDataSetとTDataSetProviderを併用する必要がありました。FireDACのデータセットはTClientDataSetとTDataSetProviderを利用しなくてもTDBGridへ表示ができるため、不要です。これはBDEを利用している場合も同様です。
TFDMemTableの利用
TFDMemTableは、上述しましたようにTClientDataSetと類似する機能を持っているため、TClientDataSetライクな使い方ができます。もしローカルデータセットなどの用途で利用する場合には、TFDMemTableへ置き換えてください。
TClientDataSetのデータをTFDMemTableへ移行するアプリケーション作成の演習
このセクションでは、実際にTClientDataSetのデータをTFDMemTableへ移行するアプリケーション作成の演習を行います。
演習手順は以下の通りです。
- TClientDataSetでサンプルデータ(XMLファイル)を読み込む
- TClientDataSetのデータをTFDMemTableへコピーし、JSONファイルに保存
- 2.で保存したJSONファイルをTFDMemTableで読み込んで、データを表示する
この演習では、手順をよりシンプルにするために、データモジュールは使用しません。
(1) VCLフォームアプリケーションのプロジェクト作成
Delphi/C++Builderのメニューから[ファイル]-[新規作成]-[Windows VCLフォームアプリケーション]を選択します。
(2) プロジェクトを保存する
メニューの[ファイル]-[すべて保存] を選択し、全てのファイルを保存してください。プロジェクトは、任意のフォルダに保存することができます。
(3) フォーム上にコンポーネントを配置する
ツールパレットの[Data Access]カテゴリから
・TClientDataSet
ツールパレットの[FireDAC]カテゴリから
・TFDMemTable
ツールパレットの[FireDAC Links]カテゴリから
・TFDStanStorageJSONLink
・TFDStanStorageXXXLinkは、FireDACでストリーミングをサポートするコンポーネントです。
バイナリ形式/JSON形式/XML形式の3種類のデータフォーマットを扱うことができ、それぞれTFDStanStorageXXXLinkのXXXには、選択しているデータフォーマットに合わせてBin/JSON/XMLが入ります。 今回は、JSON形式のファイルを扱いますので、TFDStanStorageJSONLinkコンポーネントを配置してください。 |
ツールパレットの[Data Access]カテゴリから
・TDataSource
ツールパレットの[Data Controls]カテゴリから
・TDBGrid
ツールパレットの[Standard]カテゴリから
・TButton
を2つ
フォーム上の任意の位置へ配置します(下図のは配置例を参照)。
(4) それぞれのプロパティを変更する
オブジェクトインスペクタの画面から各コンポーネントの以下のプロパティを変更します。
プロパティ名 | 値 |
DataSource | DataSource1 |
プロパティ名 | 値 |
Caption | ClientDataSetのデータを保存 |
プロパティ名 | 値 |
Caption | FDMemTableでデータを読み込む |
(5) ClientDataSetのデータを保存する処理を実装する
この演習では、ClientDataSetのデータを読み込むために、サンプルのデータファイルを使用します。
サンプルのデータファイルは、以下のパスに配置されています。
1 |
C:\Users\Public\Documents\Embarcadero\Studio\xxx\Samples\Data |
xxxには、Delphi/C++Builderのバージョンに対応した値が入ります。
(例えば、10.3の場合は、20.0 、 10.4の場合は、21.0)
Delphi/C++Builderのインストール選択時に、サンプルコードも一緒にインストールしていない場合は、サンプルのデータファイルも配置されませんのでご注意ください。 |
設計画面でButton1をダブルクリックすると、Button1のOnClickのイベントハンドラが生成されます。そのイベントハンドラ内にデータセットを開く処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
procedure TForm1.Button1Click(Sender: TObject); const // 10.4のサンプルデータのパス Data= 'C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Data\'; begin // 今回は例としてDataフォルダにあるemployee.xmlを読み込む ClientDataSet1.LoadFromFile(Data+'employee.xml'); // ClientDataSetのデータをFDMemTableへコピー FDMemTable1.CopyDataSet(ClientDataSet1,[coStructure,coRestart, coAppend]); //FDMemTableのデータをJSONファイルとして保存 FDMemtable1.SaveToFile(Data+'employee.json',sfJSON); end; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void __fastcall TForm1::Button1Click(TObject *Sender) { // 10.4のサンプルデータのパス const UnicodeString Data=L"C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\21.0\\Samples\\Data\\"; // 今回は例としてDataフォルダにあるemployee.xmlを読み込む ClientDataSet1->LoadFromFile(Data+L"employee.xml"); // ClientDataSetのデータをFDMemTableへコピー FDMemTable1->CopyDataSet(ClientDataSet1,TFDCopyDataSetOptions() << coStructure << coRestart << coAppend); //FDMemTableのデータをJSONファイルとして保存 FDMemTable1->SaveToFile(Data+L"employee.json",TFDStorageFormat::sfJSON); } |
データセットのインポート/エクスポートを行うためには、LoadFromFileメソッドとSaveToFileメソッドを使用します。
なお、ClientDataSetで出力したファイルは、FDMemTableで直接読み込むことはできません。その逆も同じです。ClientDataSetとFDMemTableは互いに内部のデータフォーマットに互換性がありません。 |
ファイルのデータフォーマットと同じく、データセットクラスも互換性が無いため、以下のようにDataプロパティを直接代入できません。
ClientDataSet1.Data := FDMemTable1.Data; ClientDataSetのデータをFDMemTableへコピーするには、CopyDataSetメソッドを利用してください。 |
(6)FDMemTableでデータを読み込む処理を実装する
設計画面でButton2をダブルクリックすると、Button2のOnClickのイベントハンドラが生成されます。そのイベントハンドラ内にデータセットを開く処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 |
procedure TForm1.Button2Click(Sender: TObject); const // 10.4のサンプルデータのパス Data= 'C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Data\'; begin DataSource1.DataSet:=FDMemTable1; //JSONファイルのデータをFDMemTableへ読み込む FDMemTable1.LoadFromFile(Data+'employee.json',sfJSON); end; |
1 2 3 4 5 6 7 8 9 10 11 |
void __fastcall TForm1::Button2Click(TObject *Sender) { // 10.4のサンプルデータのパス const UnicodeString Data=L"C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\21.0\\Samples\\Data\\"; DataSource1->DataSet=FDMemTable1; //JSONファイルのデータをFDMemTableへ読み込む FDMemTable1->LoadFromFile(Data+L"employee.json",TFDStorageFormat::sfJSON); } |
(7)プロジェクトを保存する
メニューの[ファイル]-[すべて保存] を選択し、全てのファイルを保存してください。
(8)アプリケーションを実行する
ツールバー(上図)の実行ボタン、または、キーボードの[F9]ボタンを押します。
(9)アプリケーションの動作を検証する
アプリケーションを実行し、[ClientDataSetのデータを保存]ボタンを押してください。もしエラーが発生してなければ、サンプルプログラムのDataフォルダにemployee.jsonというファイルが作成されているでしょう。
ファイルが作成されていたら、[FDMemTableでデータを読み込む]ボタンを押します。正常にjsonファイルのデータが読み込まれると、下図のようにDBGridにデータが表示されます。
今回の演習では、できるだけシンプルにするためにデータの入出力はファイル経由で行いましたが、実際のデータベースに接続し、データの取得や更新も行えます。旧バージョンで作成したプロジェクトでTClientDataSetを利用している場合は、ぜひTFDMemTableへの置き換えを検討してください。
次回は、FireDACのパフォーマンスチューニングのヒントについて説明いたします。
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition