チュートリアル:アプリケーションで FireDAC により REST DataSnap サーバーを使用する
データベースおよび LiveBinding のチュートリアル への移動
このチュートリアルでは、DataSnap フレームワークを使用した多層データベース アプリケーションを構築します。サーバーは、InterBase データベースのデータにアクセスする Web アプリケーションです。クライアントは、DataSnap REST クライアント モジュールを含んだマルチデバイス アプリケーションです。クライアントは、HTTP プロトコルを使ってサーバーに接続し、REST インターフェイスによって JSON データを交換します。
このチュートリアルでは、以下の技術を使用します。
- データベース: Interbase
- データベース アクセス フレームワーク: FireDAC
- データ形式: JSON
- クライアント/サーバー アーキテクチャ: REST
- 通信プロトコル: HTTP
- クライアント側のメモリ内データセット: FireDAC TFDMemTable
- UI 技術: ビジュアル LiveBinding
Delphi のデモが C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\Delphi\DataSnap\FireDACJSONReflect にあります。
DataSnap REST アプリケーションの作成
- プロジェクトを新規作成します。
- メイン メニューから[ファイル|新規作成|その他...]を選択します。
- C++Builder プロジェクトまたは Delphi プロジェクト ノード下の、左列の[DataSnap Server]ノードに移動します。
- [DataSnap REST アプリケーション]を選択し、[OK]をクリックします。
- 以下の手順で、アプリケーションの種類を指定します。
- [スタンドアロン アプリケーション]を選択し、[次へ]をクリックします。
- 次のいずれかのオプションを選択します。
- [VCL アプリケーション]
- [FireMonkey アプリケーション]
- デフォルト値のまま HTTP 通信プロトコルを使用するとして、[次へ]を押します。
- メモ: [ポートのテスト]をクリックして、ポートが空いているかをチェックします。
- デフォルトで選択されている[サーバー メソッド クラス]とサンプル(サーバー上のメソッド宣言の例を見たい場合)のオプションをそのまま使用します。
- サーバー クラスを完全に実装するための[TDataModule]を選択し、[次へ >>]をクリックします。このオプションを選択すると、データベースに接続するための FireDAC コンポーネントを配置できるフォームが追加されます。
- プロジェクトの場所とプロジェクトのフォルダ名を選択し、[完了]をクリックします。
- Form1 の Caption プロパティを「ServerForm」に変更します。
- メイン メニューの[ファイル|すべて保存]を選択します。
- FormUnit1 を ServerUnit、WebModuleUnit1 を WebModuleUnit1、ServerMethodsUnit1 を ServerMethodsUnit1、プロジェクトを MyServerProj という名前でそれぞれ保存します。
主な DataSnap サーバー コンポーネント
[DataSnap REST アプリケーション]を作成した段階で、必要なすべての DataSnap コンポーネントが自動的に WebModuleUnit1 ユニットに追加されています。
WebModuleUnit1 ユニットの主なコンポーネントは次のとおりです。
TDSServer コンポーネントは、DataSnap サーバー アプリケーションのロジックの中心部分です。サーバーを開始する Start メソッドと、停止する Stop メソッドが含まれます。1 つのサーバー アプリケーションに必要な TDSServer コンポーネントは 1 つだけです。
TDSServerClass コンポーネントはサーバー クラスを表します。DataSnap サーバーは、サーバー クラスのインスタンスを自動的に作成し、破棄します。
クライアントとサーバーの間の通信は、HTTP 通信プロトコルを使って行われます。
FireDAC コンポーネントをサーバー モジュールに追加する
ServerMethodsUnit1 ユニットに以下のコンポーネントを追加します。
- TFDConnection コンポーネント。Name プロパティを「FDConnectionEMPLOYEE」に設定します。
- コンポーネントを右クリックし、[接続エディタ...]を選択します。[FireDac 接続エディタ]ウィンドウが開き、接続パラメータを定義することができます。
- [ドライバ ID]フィールドのドロップダウン メニューから[IB]を選択します。
- Interbase データベースのパスを C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\Data\EMPLOYEE.GDB に設定します。
- User_Name と Password を設定します。これらのパラメータのデフォルト値は、User_Name が「sysdba」、Password が「masterkey」です。
- [OK]をクリックして、変更内容を保存します。
- [オブジェクト インスペクタ]で、LoginPrompt プロパティを False に変更します。
- Connected プロパティを True に設定します。
- ヒント: [データ エクスプローラ]を使用して、新しい TFDConnection コンポーネントをフォーム上にドロップすることができます。[データ エクスプローラ]で、[InterBase|EMPLOYEE]と移動し、コンポーネントをクリックし、フォームにそれをドロップします。
- InterBase データベースに接続するための 1 つの TFDPhysIBDriverLink コンポーネント。
- 1 つの TFDGUIxWaitCursor コンポーネント。
- 3 つの TFDQuery コンポーネント。
- TFDQuery コンポーネントを右クリックし、[クエリ エディタ...]をクリックして、[FireDAC クエリ エディタ]ウィンドウを開き、後ほど詳細を示しますが、SQL 文を入れていきます。
- 1 つのコンポーネントの名前を「FDQueryDepartmentNames」に変更し、「select dept_no, department from department」という SQL 文を入力し、[OK]をクリックします。このクエリは、部署番号と部署名のリストを返します。クライアントでは、このクエリの結果を使用して部署のリストを作成します。この情報を取得するには、クライアント アプリケーションで "GetDepartmentNames" というサーバー メソッドを呼び出す必要があります。
- 2 番目のコンポーネントの名前を「FDQueryDepartment」に変更し、「select * from department where DEPT_NO = :DEPT」という SQL 文を入力し、[OK]をクリックします。
- 最後のコンポーネントを FDQueryDepartmentEmployees に名前変更し、次の文を入れます:select * from employee where dept_no = :DEPT
そして[OK]をクリックします。
- メモ: 後の 2 つのクエリ(FDQueryDepartment と FDQueryDepartmentEmployees)は、特定の部署の詳細情報を DEPARTMENT テーブルおよび EMPLOYEE テーブルから取得するためのものです。どちらのクエリから返される情報も、"GetDepartmentEmployees" というサーバー メソッドでクライアントに渡されます。
- TFDStanStorageJSONLink コンポーネント
- TFDStanStorageBinLink コンポーネント
ServerMethodsUnit1 には EchoString および ReverseString という 2 つの単純なメソッドの実装が含まれていて、パラメータとして指定された値を通常の状態と逆の状態でそれぞれ返します。これらはメソッド例として含まれているだけです。
この例では、新しいメソッドを ServerMethodsUnit1 に追加して、JSON データを基となる InterBase EMPLOYEE サンプル データベースから取得し、サーバーはこれらのメソッドをクライアントに公開します。
"GetDepartmentNames" サーバー メソッド
- Delphi の場合:
このメソッドは、すべての部署を取得し、その結果の TFDJSONDataSets を返します。
{$METHODINFO ON}
public
{ Public declarations }
function GetDepartmentNames: TFDJSONDataSets;
{$METHODINFO OFF}
Ctrl+Shift+C
を押してクラス補完を使用し、この関数のスタブを implementation
セクションに作成します。
追加した関数のコードを次のように記述します。
//GetDepartmentNames
function TServerMethods1.GetDepartmentNames: TFDJSONDataSets;
begin
// Clear active so that query will reexecute.
FDQueryDepartmentNames.Active := False;
Result := TFDJSONDataSets.Create;
// The "TFDJSONDataSetsWriter" class provides static "ListAdd" method.
// It uses reflection to convert results of the query into "TFDJSONDataSets".
TFDJSONDataSetsWriter.ListAdd(Result, FDQueryDepartmentNames);
end;
この関数は、TFDJSONDataSets という新しいデータ型を返します。この型を使用するには、interface の uses セクションに、必要なユニット Data.FireDACJSONReflect を含める必要があります。このユニットは、クラス宣言と implementation セクションの両方で必要です。
- C++ の場合:
このメソッドは、すべての部署を取得し、その結果の TJSONObject を返します。
メソッド宣言は、ServerMethodsUnit1.h ファイルに入れます。
public: // User declarations
TJSONObject* GetDepartmentNames();
メソッドのコードは ServerMethodsUnit1.cpp ファイルに追加します。
TJSONObject* TServerMethods1::GetDepartmentNames() {
FDQueryDepartmentNames->Close();
TFDJSONDataSets *ds = new TFDJSONDataSets();
TFDJSONDataSetsWriter::ListAdd(ds, FDQueryDepartmentNames);
TJSONObject *obj = new TJSONObject();
TFDJSONInterceptor::DataSetsToJSONObject(ds, obj);
return obj;
}
以下のヘッダー ファイルを ServerMethodsUnit1.h ファイルに含める必要があります。
- # include <System.Json.hpp> // TJSONObject データ型
- # include <Data.FireDACJSONReflect.hpp> // TFDJSONDataSets データ型
"GetDepartmentEmployees" サーバー メソッド
このメソッドを使用すると、特定の部署の詳細情報を、FDQueryDepartment および FDQueryDepartmentEmployees を使って DEPARTMENT テーブルおよび EMPLOYEE テーブルから取得することができます。 どちらのクエリのデータも、1 つのメソッドで取得します。 そのために、2 つの定数を作成する必要があります。
- Delphi の場合:
implementation セクションの uses 文の下に定数を追加します。
const
sDepartment = 'Department';
sEmployees = 'Employees';
interface セクションのクラス宣言の中にこのメソッドの宣言を追加します。
{$METHODINFO ON}
public
{ Public declarations }
function GetDepartmentEmployees(const AID: string): TFDJSONDataSets;
{$METHODINFO OFF}
Ctrl+Shift+C
を押してクラス補完を使用し、この関数のスタブを implementation
セクションに作成します。
追加した関数のコードを次のように記述します。
function TServerMethods1.GetDepartmentEmployees(const AID: string): TFDJSONDataSets;
begin
// Clear active so that query will reexecute.
FDQueryDepartmentEmployees.Active := False;
FDQueryDepartment.Active := False;
FDQueryDepartment.Params[0].Value := AID;
FDQueryDepartmentEmployees.Params[0].Value := AID;
// Create dataset list
Result := TFDJSONDataSets.Create;
// Add departments dataset
TFDJSONDataSetsWriter.ListAdd(Result, sDepartment, FDQueryDepartment);
// Add employees dataset
TFDJSONDataSetsWriter.ListAdd(Result, sEmployees, FDQueryDepartmentEmployees);
end;
クライアント アプリケーションでは、この 2 つのメソッドを使って部署についての情報を受け取ります。まず、部署名と部署 ID のリストを取得します(GetDepartmentNames メソッド)。クライアントでリストから部署を選択すると、2 番目のサーバー メソッド(GetDepartmentEmployees)から部署の詳細情報と従業員が返されます。
- C++ の場合:
定数宣言は ServerMethodsUnit1.cpp ファイルに追加します。
const System::String sEmployees = "Employees";
const System::String sDepartment = "Department";
メソッド宣言は、ServerMethodsUnit1.h ファイルに入れます。
public: // User declarations
TJSONObject* GetDepartmentEmployees(System::UnicodeString AID);
メソッドのコードは ServerMethodsUnit1.cpp ファイルに追加します。
// Get a Department and all Employees in the department. Return TJSONObject.
TJSONObject* TServerMethods1::GetDepartmentEmployees(System::UnicodeString AID)
{
FDQueryDepartmentEmployees->Active = false;
FDQueryDepartment->Active = false;
FDQueryDepartment->Params->operator[](0)->Value = AID;
FDQueryDepartmentEmployees->Params->operator[](0)->Value = AID;
// Create dataset list
TFDJSONDataSets *ds = new TFDJSONDataSets();
// Add departments dataset
TFDJSONDataSetsWriter::ListAdd(ds, sDepartment, FDQueryDepartment);
// Add employees dataset
TFDJSONDataSetsWriter::ListAdd(ds, sEmployees, FDQueryDepartmentEmployees);
TJSONObject *obj = new TJSONObject();
TFDJSONInterceptor::DataSetsToJSONObject(ds, obj);
return obj;
}
"ApplyChangesDepartmentEmployees" サーバー メソッド
このメソッドを使用すると、データの変更をクライアントから送信して、データベースを更新することができます。このメソッドは値を返しません。このメソッドには TFDJSONDeltas のパラメータがあります。この型も Data.FireDACJSONReflect ユニットに含まれています。1 回の操作だけで複数のテーブルを更新できます。ソース コードは以下のとおりです。
- Delphi の場合:
{$METHODINFO ON}
public
{ Public declarations }
procedure ApplyChangesDepartmentEmployees(const ADeltaList: TFDJSONDeltas);
{$METHODINFO OFF}
Ctrl+Shift+C
を押してクラス補完を使用し、この関数のスタブを implementation
セクションに作成します。
追加した関数のコードを次のように記述します。
// Update department and employees using deltas
procedure TServerMethods1.ApplyChangesDepartmentEmployees(
const ADeltaList: TFDJSONDeltas);
var
LApply: IFDJSONDeltasApplyUpdates;
begin
// Create the apply object
LApply := TFDJSONDeltasApplyUpdates.Create(ADeltaList);
// Apply the department delta
LApply.ApplyUpdates(sDepartment, FDQueryDepartment.Command);
if LApply.Errors.Count = 0 then
// If no errors, apply the employee delta
LApply.ApplyUpdates(sEmployees, FDQueryDepartmentEmployees.Command);
if LApply.Errors.Count > 0 then
// Raise an exception if any errors.
raise Exception.Create(LApply.Errors.Strings.Text);
end;
- C++ の場合:
メソッド宣言は、ServerMethodsUnit1.h ファイルに入れます。
public: // User declarations
void ApplyChangesDepartmentEmployees(TJSONObject* AJSONObject);
メソッドのコードは ServerMethodsUnit1.cpp ファイルに追加します。
void TServerMethods1::ApplyChangesDepartmentEmployees(TJSONObject* AJSONObject)
{
TFDJSONDeltas *LDeltas = new TFDJSONDeltas();
TFDJSONInterceptor::JSONObjectToDataSets(AJSONObject, LDeltas);
TFDJSONErrors *errs = new TFDJSONErrors();
// Apply the department delta
TFDJSONDeltasApplyUpdates::ListApplyUpdates(LDeltas, sDepartment,
FDQueryDepartment->Command, errs);
// If no errors, apply the employee delta
if (errs->Count == 0) {
TFDJSONDeltasApplyUpdates::ListApplyUpdates(LDeltas, sEmployees,
FDQueryDepartmentEmployees->Command, errs);
}
// Raise an exception if any errors.
if (errs->Count > 0) {
throw new Exception(errs->Strings->Text);
}
}
クライアント アプリケーションを作成する前に、サーバーを実行します。
- メイン メニューから[実行|デバッガを使わずに実行]を選択します。
- [Start]ボタンをクリックします。表示される[ServerForm]ダイアログは最小化してかまいません。
このステップは非常に重要です。サーバーからデータを取得するためのクライアント クラスを作成するには、サーバーへの接続が必要だからです。
クライアント アプリケーションの作成
- サーバー アプリケーションと同じプロジェクト グループ内にクライアント アプリケーションを作成します。手順は以下のとおりです。
- [プロジェクト マネージャ]で、ProjectGroup ノードを右クリックします。
- [新規プロジェクトを追加...]オプションを選択します。
- [Delphi プロジェクト]または[C++Builder プロジェクト]の項目から[マルチデバイス アプリケーション]を選択し、[OK]をクリックします。
- [空のアプリケーション]を選択し、[OK]をクリックします。
- メイン メニューの[ファイル|新規作成|その他...]を選択します。
- 左列の[DataSnap Server]ノードから[DataSnap REST クライアント モジュール]を選択し、[OK]をクリックします。
- モジュールの種類を次のように指定します。
- デフォルト値[ローカル サーバー]を選択したままで[次へ >>]をクリックします。
- デフォルト値[DataSnap スタンドアロン サーバー]を選択したままで[次へ >>]をクリックします。
- 接続パラメータのデフォルト値のままで[完了]をクリックします。
- メモ: [接続テスト]をクリックしてサーバーとの接続を確認します。サーバーが動作していなければ、ウィザードを完了することができません。
- これで、ウィザードによって ClientModuleUnit と ClientClassesUnit が生成されます。
- Form2 の Caption プロパティを「ClientForm」に変更します。
- メイン メニューの[ファイル|すべて保存]を選択します。
- Unit2 を ClientUnit、ClientModuleUnit1 を ClientModuleUnit1、ClientClassesUnit1 を ClientClassesUnit1、プロジェクトを MyClientProj という名前でそれぞれ保存します。
- プロジェクト グループを DSServerExample という名前で保存します。
- クライアント フォームに以下のコントロールおよびコンポーネントを追加します。
- TButton コンポーネント。text プロパティを「Get Departments」に変更します。
- TButton コンポーネント。text プロパティを「Apply Updates」に変更します。
- TListView コンポーネント。name プロパティを「ListViewDepartments」に変更します。
- TStringGrid コンポーネント。name プロパティを「StringGridDepartment」に変更します。
- TStringGrid コンポーネント。name プロパティを「StringGridEmployee」に変更します。
- TFDMemTable コンポーネント。name プロパティを「FDMemTableDepartments」に変更します。このデータセットは、部署番号と部署名のリストを含む読み取り専用データの格納にのみ使用します。
- 設計時にバインドするためのフィールド定義を TFDMemTable に作成する必要があります。[構造]パネルで FieldDefs を右クリックし、[項目を追加]をクリックして、0 - DEPARTMENT および 1 - DEPT_NO という 2 つの新しい項目を追加します。
- メモ: フィールドの型は重要ではありませんが、フィールド定義の名前はサーバーから取得したデータセット内のフィールドと対応している必要があります。
- 設計時にバインドするためのフィールド定義を TFDMemTable に作成する必要があります。[構造]パネルで FieldDefs を右クリックし、[項目を追加]をクリックして、0 - DEPARTMENT および 1 - DEPT_NO という 2 つの新しい項目を追加します。
- TFDMemTable コンポーネント。name プロパティを FDMemTableDepartment に変更します。
- CachedUpdates プロパティを True に変更します。
- TFDMemTable コンポーネント。name プロパティを FDMemTableEmployee に変更します。
- CachedUpdates プロパティを True に変更します。
- TFDStanStorageJSONLink コンポーネント
- TFDStanStorageBinLink コンポーネント。
[LiveBinding デザイナ]を使用する
ビジュアル ライブ バインディングを使用してデータをビジュアル コントロールにバインドします。
- [表示|LiveBinding デザイナ]を選択して[LiveBinding デザイナ]ウィンドウを開きます。
- TListView の ItemAppearance.ItemAppearance プロパティを ListItemRightDetail に変更して、TListView に Item.Detail プロパティを追加します。
- FDMemTableDepartments の DEPARTMENT フィールドを Item.Text にバインドします。
- FDMemTableDepartments の DEPT_NO フィールドを Item.Detail にバインドします。
- StringGridDepartment と FDMemTableDepartment をバインドします。
- StringGridEmployee と FDMemTableEmployee をバインドします。
クライアントでサーバー メソッドを呼び出す
データを取得するには、クライアント アプリケーションでサーバー メソッドを呼び出す必要があります。
- メモ: サーバー メソッドの定義を変更した場合には、サーバーを再起動する必要があります。 サーバーを再起動した後、プロキシも更新する必要があります。それには、ClientModuleUnit の TDSRestConnection コンポーネントを右クリックし、コンテキスト メニューの [DataSnap クライアント クラスの生成]をクリックします。
GetDepartmentNames
Delphi の場合:
ClientUnit フォームに ClientModuleUnit1 を追加します。ユニットを、interface セクションまたは implementation セクションの uses 文に追加します。
- メモ: ウィザードを使ってユニットを追加するには、[ファイル|使用するユニット...]を選択します。[使用するユニット]ウィンドウが開き、現在のファイルに追加したいユニットを選択することができます。
TFDJSONDataSets データ型を使用するには、implementation セクションの uses 文に、必要なユニット Data.FireDACJSONReflect を追加する必要があります。
private
{ Private declarations }
procedure GetDepartmentNames;
procedure TForm2.GetDepartmentNames;
var
//To use this type you need to include a new unit in the uses section: Data.FireDACJSONReflect.
LDataSetList: TFDJSONDataSets;
begin
// It empties the memory table of any existing data before adding the new context.
FDMemTableDepartments.Close;
// Get dataset list containing Employee names
LDataSetList := ClientModule1.ServerMethods1Client.GetDepartmentNames;
// Reads the first and only dataset, number 0.
FDMemTableDepartments.AppendData(
TFDJSONDataSetsReader.GetListValue(LDataSetList, 0));
//It uses a reader from The "TFDJSONDataSetsWriter" class to populate the memory table from the dataset list class.
FDMemTableDepartments.Open;
end;
GetDepartmentNames 手続きを呼び出すよう OnClick イベントを実装します。
procedure TForm2.Button1Click(Sender: TObject);
begin
GetDepartmentNames; //Calling this method populates the TListView.
end;
- C++ の場合:
以下のヘッダー ファイルを ClientUnit.h ファイルに追加します。
- # include <Memory>// このヘッダーには動的メモリを管理する汎用ユーティリティが定義されている
- # include <Data.FireDACJSONReflect.hpp>
- # include <DataSnap.DSClientREST.hpp>
- # include <ClientModuleUnit1.h>
メソッド宣言は、ClientUnit.h ファイルに入れます。
public: // User declarations
void GetDepartmentNames();
このコードは、ClientUnit.cpp ファイルに入ります。
void TForm2::GetDepartmentNames() {
// Gets JSON data from the server using "ClientModule1" class that was generated with the "DataSnap REST Client Module" wizard.
TJSONObject* LJSONObject
(ClientModule1->ServerMethods1Client->GetDepartmentNames());
std::auto_ptr<TFDJSONDataSets>LDataSets(new TFDJSONDataSets());
// Automatic Pointer.
// Converts JSON to a dataset, just the opposite that in the server.
TFDJSONInterceptor::JSONObjectToDataSets(LJSONObject, LDataSets.get());
FDMemTableDepartments->Active = false;
TFDAdaptedDataSet * LDataSet = TFDJSONDataSetsReader::GetListValue
(LDataSets.get(), 0);
FDMemTableDepartments->AppendData(*LDataSet);
// Appends the DataSet to FDMemTableDepartment table.
}
void __fastcall TForm2::Button1Click(TObject *Sender)
{
GetDepartmentNames(); //Calling this method populates the TListView.
}
GetDepartmentEmployees
このメソッドは、選択した部署について、部署や従業員の詳細情報をダウンロードするためのものです。このコードは、TListView で部署名をクリックしたときに実行されます。
定数は interface セクションまたは implementation セクションに置きますが、コードに近い方がコードを読んで理解しやすくなります。
const
sEmployees = 'Employees';
sDepartment = 'Department';
private
{ Private declarations }
procedure GetDepartmentEmployees(const ADEPTNO: string);
procedure TForm2.GetDepartmentEmployees(const ADEPTNO: string);
var
LDataSetList: TFDJSONDataSets;
LDataSet: TFDDataSet;
begin
LDataSetList := ClientModule1.ServerMethods1Client.GetDepartmentEmployees(ADEPTNO);
// Get department dataset
LDataSet := TFDJSONDataSetsReader.GetListValueByName(LDataSetList,sDepartment);
// Update UI
FDMemTableDepartment.Active := False;
FDMemTableDepartment.AppendData(LDataSet);
// Get employees dataset
LDataSet := TFDJSONDataSetsReader.GetListValueByName(LDataSetList, sEmployees);
// Update UI
FDMemTableEmployee.Active := False;
FDMemTableEmployee.AppendData(LDataSet);
end;
GetDepartmentEmployees 手続きを呼び出すよう TListView の OnChange イベントを実装します。
procedure TForm2.ListViewDepartmentsChange(Sender: TObject);
var
LDEPTNO: string;
begin
// Show department/employee details
LDEPTNO := TListViewItem(ListViewDepartments.Selected).Detail;
GetDepartmentEmployees(LDEPTNO);
end;
- C++ の場合:
定数宣言を ClientUnit.cpp ファイルに追加します。定数はインターフェイス部と実装部のどちらに追加してもかまいませんが、コードに近い方がコードを読んで理解しやすくなります。
const System::String sEmployees = "Employees";
const System::String sDepartment = "Department";
メソッド宣言は、ClientUnit.h ファイルに入れます。
public: // User declarations
void GetDepartmentEmployees(const System::String ADEPTNO);
このコードは、ClientUnit.cpp ファイルに入ります。
void TForm2::GetDepartmentEmployees(const System::String ADEPTNO) {
TJSONObject* LJSONObject
(ClientModule1->ServerMethods1Client->GetDepartmentEmployees(ADEPTNO));
std::auto_ptr<TFDJSONDataSets>LDataSets(new TFDJSONDataSets());
TFDJSONInterceptor::JSONObjectToDataSets(LJSONObject, LDataSets.get());
{ // multiple declaration for 'LDataSet'
TFDAdaptedDataSet * LDataSet = TFDJSONDataSetsReader::GetListValueByName
(LDataSets.get(), sDepartment);
// Update UI
FDMemTableDepartment->Active = False;
FDMemTableDepartment->AppendData(*LDataSet);
}
{ // multiple declaration for 'LDataSet'
TFDAdaptedDataSet * LDataSet = TFDJSONDataSetsReader::GetListValueByName
(LDataSets.get(), sEmployees);
// Update UI
FDMemTableEmployee->Active = False;
FDMemTableEmployee->AppendData(*LDataSet);
}
}
GetDepartmentEmployees 手続きを呼び出すよう TListView の OnChange イベントを実装します。
void __fastcall TForm2::ListViewDepartmentsChange(TObject *Sender)
{
// Show department/employee details
System::String LDEPTNO = ((TListViewItem*)(ListViewDepartments->Selected))->Detail;
GetDepartmentEmployees(LDEPTNO);
}
ApplyUpdates 手続き
"FDMemTableDepartment" および "FDMemTableEmployee" に格納されているデータは、ユーザー インターフェイスから変更することができます。ユーザーが[Apply Updates]ボタンをクリックすると、以下のコードによって更新内容がサーバーに送り返されます。
- Delphi の場合:
まず、TFDJSONDeltas を取得する関数を作成する必要があります。
private
{ Private declarations }
function GetDeltas: TFDJSONDeltas;
function TForm2.GetDeltas: TFDJSONDeltas;
begin
// Post if editing
if FDMemTableDepartment.State in dsEditModes then
begin
FDMemTableDepartment.Post;
end;
if FDMemTableEmployee.State in dsEditModes then
begin
FDMemTableEmployee.Post;
end;
// Create a delta list
Result := TFDJSONDeltas.Create;
// Add deltas
TFDJSONDeltasWriter.ListAdd(Result, sEmployees, FDMemTableEmployee);
TFDJSONDeltasWriter.ListAdd(Result, sDepartment, FDMemTableDepartment);
end;
次に、変更を適用するメソッドを作成します。
private
{ Private declarations }
procedure ApplyUpdates;
procedure TForm2.ApplyUpdates;
var
LDeltaList: TFDJSONDeltas;
begin
LDeltaList := GetDeltas;
// Call server method. Pass the delta list.
ClientModule1.ServerMethods1Client.ApplyChangesDepartmentEmployees(LDeltaList);
end;
ApplyUpdates 手続きを呼び出すよう OnClick イベントを実装します。
procedure TForm2.ButtonApplyUpdatesClick(Sender: TObject);
begin
ApplyUpdates;
end;
- C++ の場合:
メソッド宣言は、ClientUnit.h ファイルに入れます。
public: // User declarations
void ApplyUpdates();
このコードは、ClientUnit.cpp ファイルに入ります。
void TForm2::ApplyUpdates() {
// Post if editing
if (dsEditModes.Contains(FDMemTableDepartment->State)) {
FDMemTableDepartment->Post();
}
if (dsEditModes.Contains(FDMemTableEmployee->State)) {
FDMemTableEmployee->Post();
}
// Create a delta list
TFDJSONDeltas * LDeltas = new TFDJSONDeltas();
// Add deltas
TFDJSONDeltasWriter::ListAdd(LDeltas, sEmployees, FDMemTableEmployee);
TFDJSONDeltasWriter::ListAdd(LDeltas, sDepartment, FDMemTableDepartment);
TJSONObject * LJSONObject(new TJSONObject());
TFDJSONInterceptor::DataSetsToJSONObject(LDeltas, LJSONObject);
// Call server method. Pass the delta list.
ClientModule1->ServerMethods1Client->ApplyChangesDepartmentEmployees
(LJSONObject);
}
ApplyUpdates 手続きを呼び出すよう OnClick イベントを実装します。
void __fastcall TForm2::Button2Click(TObject *Sender)
{
ApplyUpdates();
}