Tutorial: Verwenden eines DataSnap-REST-Servers mit einer Anwendung und FireDAC

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Tutorials zu Datenbanken und LiveBindings


Führen Sie die Schritte in diesem Tutorial aus, um eine mehrschichtige Datenbankanwendung mit dem DataSnap-Framework zu erzeugen. Der Server ist eine Webanwendung, die auf Daten aus einer InterBase-Datenbank zugreift. Der Client ist eine geräteübergreifende Anwendung, die ein DataSnap-REST-Clientmodul enthält. Der Client verwendet das HTTP-Protokoll, um eine Verbindung zum Server herzustellen und JSON-Daten über REST-Interfaces auszutauschen.

In diesem Tutorial werden den folgenden Technologien verwendet:

  • Datenbank: InterBase
  • Framework für den Datenbankzugriff: FireDAC
  • Datenformat: JSON
  • Client/Server-Architektur: REST
  • Kommunikationsprotokoll: HTTP
  • Clientseitige Datenmenge im Arbeitsspeicher: FireDAC TFDMemTable
  • UI-Technologie: Visuelle LiveBindings

Eine Delphi-Demo befindet sich in C:\Users\Public\Documents\Embarcadero\Studio\\Samples\Delphi\DataSnap\FireDACJSONReflect.

Erstellen der DataSnap-REST-Anwendung

  1. Erstellen Sie ein neues Projekt:
    • Wählen Sie im Hauptmenü Datei > Neu > Weitere.
    • Erweitern Sie in der linken Spalte unter "C++Builder-Projekte" oder "Delphi-Projekte" den Knoten DataSnap-Server.
    • Wählen Sie DataSnap-REST-Anwendung, und klicken Sie auf "OK".
    • Legen Sie den Anwendungstyp fest:
      1. Wählen Sie Eigenständige Anwendung aus und klicken Sie auf Weiter.
      2. Wählen Sie eine der folgenden Optionen aus:
        • VCL-Anwendung
        • FireMonkey-Anwendung
      3. Behalten Sie die Vorgabewerte bei, damit das HTTP-Kommunikationsprotokoll verwendet wird, und klicken Sie auf Weiter.
        Hinweis: Klicken Sie auf Port testen, um zu überprüfen, ob der Port frei ist.
      4. Behalten Sie die standardmäßig ausgewählten Optionen Server-Methodenklassen und "Beispielmethoden" bei, wenn Sie ein Beispiel der Methodendeklaration auf dem Server haben möchten.
      5. Wählen Sie TDataModule aus, um die Serverklasse vollständig zu implementieren, und klicken Sie auf Weiter. Diese Option fügt ein Formular hinzu, auf dem Sie die FireDAC-Komponenten für die Verbindung mit der Datenbank platzieren können.
      6. Wählen Sie den Speicherort und den Ordnernamen für das Projekt aus, und klicken Sie auf Fertig stellen.
  2. Ändern Sie die Eigenschaft Caption von Form1 in ServerForm.
    ServerFormDSTutorial.png
  3. Klicken Sie im Hauptmenü auf Datei > Alles speichern.
  4. Speichern Sie FormUnit1 unter ServerUnit, WebModuleUnit1 unter WebModuleUnit1, ServerMethodsUnit1 unter ServerMethodsUnit1 und das Projekt unter MyServerProj.

Wichtige DataSnap-Serverkomponenten

Wenn Sie die DataSnap-REST-Anwendung erstellen, werden alle erforderlichen DataSnap-Komponenten automatisch der Unit WebModuleUnit1 hinzugefügt.

WebModuleDSApplication.png

Hauptkomponenten in der Unit WebModuleUnit1:

Die TDSServer-Komponente ist das logische Herz der DataSnap-Serveranwendung. Sie enthält die Methoden Start und Stop zum Starten und Anhalten des Servers. Sie benötigen nur eine TDSServer-Komponente pro Serveranwendung.

Die Komponente TDSServerClass repräsentiert eine Serverklasse. Der DataSnap-Server erstellt automatisch Instanzen der Serverklassen und gibt diese auch automatisch frei.

Das HTTP-Kommunikationsprotokoll ermöglicht die Kommunikation zwischen Client und Server.

Hinzufügen von FireDAC-Komponenten zum Servermodul

Fügen Sie der Unit ServerMethodsUnit1 die folgenden Komponenten hinzu:

  • Eine TFDConnection-Komponente. Setzen Sie deren Eigenschaft Name auf "FDConnectionEMPLOYEE".
    • Klicken Sie mit der rechten Maustaste auf die Komponente, und wählen Sie Verbindungseditor. Das Fenster FireDAC-Verbindungseditor wird geöffnet, in dem Sie die Verbindungsparameter festlegen müssen.
    • Wählen Sie aus der Dropdown-Liste des Feldes Treiber-ID den Eintrag IB aus.
    • Legen Sie den Pfad zur InterBase-Datenbank: C:\Users\Public\Documents\Embarcadero\Studio\\Samples\Data\EMPLOYEE.GDB fest.
    • Legen Sie User_Name und Password fest. Die Vorgabewerte für diese Parameter lauten: User_Name = sysdba und Password = masterkey.
    • Klicken Sie zum Speichern der Änderungen auf OK.
    • Ändern Sie im Objektinspektor die Eigenschaft LoginPrompt in False.
    • Setzen Sie Eigenschaft Connected auf True.
    • Tipp: Mit dem Daten-Explorer können Sie eine neue TFDConnection-Komponente auf Ihrem Formular ablegen. Wechseln Sie zu InterBase > EMPLOYEE, klicken Sie auf die Komponente, und legen Sie sie auf dem Formular ab.
  • Eine TFDPhysIBDriverLink-Komponente für die Verbindung mit einer InterBase-Datenbank.
  • Eine TFDGUIxWaitCursor-Komponente.
  • Drei TFDQuery-Komponenten.
    • Klicken Sie mit der rechten Maustaste auf die TFDQuery-Komponente, und klicken Sie auf Abfrageeditor, um das Fenster FireDAC-Abfrageeditor für die Eingabe der SQL-Anweisungen (werden weiter unten behandelt) zu öffnen.
    • Benennen Sie eine Komponente in FDQueryDepartmentNames um, und geben Sie die folgende SQL-Anweisung ein: select dept_no, department from department. Klicken Sie anschließend auf "OK". Diese Abfrage gibt eine Liste der Abteilungsnummern und -namen zurück. Anhand dieses Ergebnisses wird auf dem Client die Liste der Abteilungen erstellt. Zum Abrufen dieser Informationen muss die Client-App die Servermethode "GetDepartmentNames" aufrufen.
    • Benennen Sie die zweite Komponente in FDQueryDepartment um, und geben Sie die folgende SQL-Anweisung ein: select * from department where DEPT_NO = :DEPT. Klicken Sie anschließend auf "OK".
    • Benennen Sie die letzte Komponente in FDQueryDepartmentEmployees um, und geben Sie die folgende Anweisung ein: select * from employee where dept_no = :DEPT. Klicken Sie anschließend auf "OK".
      Hinweis:: Mit den beiden letzten Abfragen, FDQueryDepartment und FDQueryDepartmentEmployees, werden detailliertere Informationen für eine gegebene Abteilung aus den Tabellen DEPARTMENT und EMPLOYEE abgerufen. Die von den beiden Abfragen zurückgegebenen Informationen werden mit der Servermethode "GetDepartmentEmployees" für Clients bereitgestellt.
  • Eine TFDStanStorageJSONLink-Komponente.
  • Eine TFDStanStorageBinLink-Komponente.

ServerMethodsUnit1 enthält die Implementierung zweier einfacher Methoden (EchoString und ReverseString), die den als Parameter übergebenen Wert im normalen bzw. im umgekehrten Status zurückgeben. Dies sind nur Beispielmethoden.

In diesem Beispiel werden ServerMethodsUnit1 neuen Methoden hinzugefügt, um JSON-Daten von der zugrunde liegenden InterBase-Beispieldatenbank EMPLOYEE abzurufen, und der Server stellt diese Methoden für den Client bereit.

Servermethode "GetDepartmentNames"

  • In Delphi:

Diese Methode ruft alle Abteilungen ab und gibt ein TFDJSONDataSets als Ergebnis zurück.

{$METHODINFO ON}
public
    { Public declarations }
function GetDepartmentNames: TFDJSONDataSets;
{$METHODINFO OFF}

Rufen Sie durch Drücken von STRG+UMSCHALT+C die Klassenvervollständigung auf, um im implementation-Abschnitt einen Rumpf (Stub) für diese Funktion zu erstellen.

Schreiben Sie den Quellcode für die gerade hinzugefügte Funktion.

//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;

Die Funktion gibt einen neuen Datentyp zurück: TFDJSONDataSets. Für diesen Typ müssen Sie eine erforderliche Unit in den uses-Abschnitt der Interfaces einbeziehen: Data.FireDACJSONReflect. Diese Unit ist sowohl in der Klassendeklaration als auch im implementation-Abschnitt erforderlich.

  • In C++:

Diese Methode ruft alle Abteilungen ab und gibt ein TJSONObject als Ergebnis zurück.

Die Deklaration der Methode muss in der Datei ServerMethodsUnit1.h erfolgen.

public:     // User declarations
    TJSONObject* GetDepartmentNames();

Der Code der Methode muss in die Datei ServerMethodsUnit1.cpp eingefügt werden.

TJSONObject* TServerMethods1::GetDepartmentNames() {
    FDQueryDepartmentNames->Close();

    TFDJSONDataSets *ds = new TFDJSONDataSets();
    TFDJSONDataSetsWriter::ListAdd(ds, FDQueryDepartmentNames);

    TJSONObject *obj = new TJSONObject();
    TFDJSONInterceptor::DataSetsToJSONObject(ds, obj);
    return obj;
}

Diese Header-Dateien müssen in die Datei ServerMethodsUnit1.h eingefügt werden:

  1. # include <System.Json.hpp> //TJSONObject-Datentyp
  2. # include <Data.FireDACJSONReflect.hpp> //TFDJSONDataSets-Datentyp

Servermethode "GetDepartmentEmployees"

Verwenden Sie diese Methode und FDQueryDepartment und FDQueryDepartmentEmployees, um detailliertere Informationen für eine gegebene Abteilung aus den Tabellen DEPARTMENT und EMPLOYEE abzurufen. Sie können mit nur einer Methode Daten aus beiden Abfragen abrufen. Dazu müssen Sie zwei Konstanten anlegen.

  • In Delphi:

Fügen Sie die Konstanten in den implementation-Abschnitt unter einer uses-Anweisung ein.

const
  sDepartment = 'Department';
  sEmployees = 'Employees';

Fügen Sie diese Methodendeklaration im interface-Abschnitt in die Klassendeklaration ein.

{$METHODINFO ON}
public
    { Public declarations }
function GetDepartmentEmployees(const AID: string): TFDJSONDataSets;
{$METHODINFO OFF}

Rufen Sie durch Drücken von STRG+UMSCHALT+C die Klassenvervollständigung auf, um im implementation-Abschnitt einen Rumpf (Stub) für diese Funktion zu erstellen.

Schreiben Sie den Quellcode für die gerade hinzugefügte Funktion.

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;

Eine Client-App ruft mit diesen beiden Methoden Informationen über Abteilungen ab. Zuerst wird die Liste der Abteilungsnamen und deren IDs ermittelt (GetDepartmentNames-Methode). Wenn ein Client eine Abteilung aus der Liste auswählt, dann werden die detaillierten Informationen über die Abteilung und ihre Mitarbeiter aus der zweiten Servermethode (GetDepartmentEmployees) zurückgegeben.

  • In C++:

Fügen Sie die Konstantendeklaration in die Datei ServerMethodsUnit1.cpp ein.

const System::String sEmployees = "Employees";
const System::String sDepartment = "Department";

Die Deklaration der Methode muss in der Datei ServerMethodsUnit1.h erfolgen.

public:     // User declarations
    TJSONObject* GetDepartmentEmployees(System::UnicodeString AID);

Der Code der Methode muss in die Datei ServerMethodsUnit1.cpp eingefügt werden.

// 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;
}

Servermethode "ApplyChangesDepartmentEmployees"

Mit dieser Methode senden Sie Datenaktualisierungen vom Client und aktualisieren die zugrunde liegende Datenbank. Diese Methode gibt keine Werte zurück. Diese Methode verwendet den Parameter TFDJSONDeltas. Dieser Typ ist auch in der Unit Data.FireDACJSONReflect enthalten. Damit können mehrere Tabellen in nur einem Vorgang aktualisiert werden. Quelltext der Methode:

  • In Delphi:
{$METHODINFO ON}
public
    { Public declarations }
    procedure ApplyChangesDepartmentEmployees(const ADeltaList: TFDJSONDeltas);
{$METHODINFO OFF}

Rufen Sie durch Drücken von STRG+UMSCHALT+C die Klassenvervollständigung auf, um im implementation-Abschnitt einen Rumpf (Stub) für diese Funktion zu erstellen.

Schreiben Sie den Quellcode für die gerade hinzugefügte Funktion.

// 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;
  • In C++

Die Deklaration der Methode muss in der Datei ServerMethodsUnit1.h erfolgen.

public:     // User declarations
    void ApplyChangesDepartmentEmployees(TJSONObject* AJSONObject);

Der Code der Methode muss in die Datei ServerMethodsUnit1.cpp eingefügt werden.

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);
    }

}

Führen Sie vor dem Erstellen der Client-Anwendung den Server aus:

  • Wählen Sie im Hauptmenü Start > Ohne Debugger ausführen .
  • Klicken Sie auf die Schaltfläche Start. Sie können das angezeigte Dialogfeld ServerForm minimieren.

Dieser Schritt ist sehr wichtig, weil Sie eine Verbindung mit dem Server benötigen, um die erforderlichen Client-Klassen für das Abrufen der Daten vom Server zu erstellen.

Erstellen der Client-Anwendung

  1. Führen Sie die folgenden Schritte aus, um die Client-Anwendung in derselben Projektgruppe wie die Serveranwendung zu erstellen:
    • Klicken Sie in der Projektverwaltung mit der rechten Maustaste auf den Knoten Projektgruppe.
    • Wählen Sie die Option Neues Projekt hinzufügen aus.
    • Wählen Sie aus der Kategorie Delphi- oder C++Builder-Projekte Geräteübergreifende Anwendung aus, und klicken Sie auf OK.
    • Wählen Sie Leere Anwendung aus, und klicken Sie auf OK .
    • Klicken Sie im Hauptmenü auf Datei > Neu > Weitere.
    • Markieren Sie im linken Bereich den Knoten DataSnap-Server, wählen Sie rechts DataSnap-REST-Client-Modul aus, und klicken Sie auf OK.
      RESTClientModuleMenu.png
    • Legen Sie den Typ des Moduls fest:
      • Behalten Sie den ausgewählten Vorgabewert Lokaler Server bei, und klicken Sie auf Weiter.
      • Behalten Sie den ausgewählten Vorgabewert Eigenständiger DataSnap-Server bei, und klicken Sie auf Weiter.
      • Behalten Sie die Standardwerte für die Verbindungsparameter bei, und klicken Sie auf Fertig stellen.
        • Hinweis: Klicken Sie auf Verbindung testen, um die Verbindung mit dem Server zu prüfen. Wenn der Server nicht ausgeführt wird, können Sie den Experten nicht abschließen.
      Der Experte generiert nun die Units ClientModuleUnit und ClientClassesUnit.
  2. Ändern Sie die Eigenschaft Caption von Form2 in ClientForm.
  3. Klicken Sie im Hauptmenü auf Datei > Alles speichern.
  4. Speichern Sie Unit2 unter ClientUnit, ClientModuleUnit1 unter ClientModuleUnit1, ClientClassesUnit1 unter ClientClassesUnit1 und das Projekt unter MyClientProj.
  5. Speichern Sie die Projektgruppe unter dem Namen DSServerExample.
  6. Fügen Sie die folgenden Steuerelemente und Komponenten in das Client-Formular ein:
    • Eine TButton-Komponente. Ändern Sie die Eigenschaft Text in "Get Departments".
    • Eine TButton-Komponente. Ändern Sie die Eigenschaft Text in "Apply Updates".
    • Eine TListView-Komponente. Ändern Sie die Eigenschaft Name in "ListViewDepartments".
    • Eine TStringGrid-Komponente. Ändern Sie die Eigenschaft Name in "StringGridDepartment".
    • Eine TStringGrid-Komponente. Ändern Sie die Eigenschaft Name in "StringGridEmployee".
    • Eine TFDMemTable-Komponente. Ändern Sie die Eigenschaft Name in "FDMemTableDepartments". Diese Datenmenge wird nur zum Speichern der schreibgeschützten Daten mit der Liste der Abteilungsnummern und Abteilungsnamen verwendet.
      • In TFDMemTable sind Felddefinitionen erforderlich, um sie zur Entwurfszeit zu binden. Klicken Sie in der Strukturansicht mit der rechten Maustaste auf FieldDefs, und klicken Sie dann auf Eintrag hinzufügen, um zwei neue Einträge hinzuzufügen: 0 - DEPARTMENT und 1 - DEPT_NO.
        • Hinweis: Feldtypen sind nicht wichtig, aber die Namen der Felddefinitionen müssen mit den Feldern in vom Server erhaltenen Datenmengen übereinstimmen.
    • Eine TFDMemTable-Komponente. Ändern Sie die Eigenschaft Name in "FDMemTableDepartment".
      • Ändern Sie die Eigenschaft CachedUpdates in True.
    • Eine TFDMemTable-Komponente. Ändern Sie die Eigenschaft Name in "FDMemTableEmployee".
      • Ändern Sie die Eigenschaft CachedUpdates in True.
    • Eine TFDStanStorageJSONLink-Komponente.
    • Eine TFDStanStorageBinLink-Komponente.

Verwenden des LiveBindings-Designers

Verwenden Sie visuelle LiveBindings, um Daten visuell an Steuerelemente zu binden.

  • Öffnen Sie mit Ansicht > LiveBindings-Designer das Fenster des LiveBindings-Designers.
  • Ändern Sie die Eigenschaft ItemAppearance > ItemAppearance der TListView in ListItemRightDetail, um der TListView die Eigenschaft Item.Detail hinzuzufügen.
  • Binden Sie das Feld DEPARTMENT von FDMemTableDepartments an Item.Text.
  • Binden Sie das Feld DEPT_NO von FDMemTableDepartments an Item.Detail.
  • Binden Sie StringGridDepartment an FDMemTableDepartment.
  • Binden Sie StringGridEmployee an FDMemTableEmployee.
RestClientModuleApp.png

Aufrufen der Servermethoden auf dem Client

Sie müssen die Servermethoden in der Client-Anwendung aufrufen, um die Daten abzurufen.

Hinweis: Wenn Sie die Definition der Servermethoden geändert haben, müssen Sie den Server neu starten. Nach dem Neustart des Servers müssen Sie auch den Proxy aktualisieren. Klicken Sie dazu in ClientModuleUnit mit der rechten Maustaste auf die Komponente TDSRestConnection, und klicken Sie im Kontextmenü auf DataSnap-Client-Klassen erzeugen.

GetDepartmentNames

In Delphi:

Beziehen Sie ClientModuleUnit1 in das ClientUnit-Formular ein. Fügen Sie die Unit in den interface- oder implementation-Abschnitt der uses-Anweisung ein.

Hinweis: Wählen Sie Datei > Unit verwenden..., um eine Unit mit dem Experten hinzuzufügen. Das Fenster Unit verwenden wird geöffnet. Hier können Sie einfach die Unit auswählen, die in die aktuelle Datei einbezogen werden soll.

Für den Datentyp TFDJSONDataSets müssen Sie im implementation-Abschnitt der uses-Anweisung eine erforderliche Unit hinzufügen: 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;

Implementieren Sie das Ereignis OnClick, um die Prozedur GetDepartmentNames aufzurufen.

procedure TForm2.Button1Click(Sender: TObject);
begin
  GetDepartmentNames; //Calling this method populates the TListView.
end;
  • In C++:

Beziehen Sie die folgenden Header-Dateien in die Datei ClientUnit.h ein:

  1. # include <Memory> // Dieser Header definiert allgemeine Hilfsfunktionen für die dynamische Speicherverwaltung.
  2. # include <Data.FireDACJSONReflect.hpp>
  3. # include <DataSnap.DSClientREST.hpp>
  4. # include <ClientModuleUnit1.h>

Die Deklaration der Methode muss in der Datei ClientUnit.h erfolgen.

public:     // User declarations
    void GetDepartmentNames();

Dieser Code muss in die Datei ClientUnit.cpp eingefügt werden.

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

Mit dieser Methode werden Abteilungs- und detaillierte Mitarbeiterinformationen für eine ausgewählte Abteilung heruntergeladen. Der Code wird beim Klicken auf die Abteilungsnamen in der TListView ausgeführt.

Fügen Sie die Konstanten in den interface- oder implementation-Abschnitt ein. Der Code wäre aber übersichtlicher, wenn die Konstanten sich näher beim Code befänden.

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;

Implementieren Sie das Ereignis OnChange der TListView, um die Prozedur GetDepartmentEmployees aufzurufen.

procedure TForm2.ListViewDepartmentsChange(Sender: TObject);
var
  LDEPTNO: string;
begin
  // Show department/employee details
  LDEPTNO := TListViewItem(ListViewDepartments.Selected).Detail;
  GetDepartmentEmployees(LDEPTNO);
end;
  • In C++:

Fügen Sie die Konstantendeklaration in die Datei ClientUnit.cpp ein. Sie können die Konstanten in den interface- oder implementation-Abschnitt einfügen. Der Code wäre aber übersichtlicher, wenn die Konstanten sich näher beim Code befänden.

const System::String sEmployees = "Employees";
const System::String sDepartment = "Department";

Die Deklaration der Methode muss in der Datei ClientUnit.h erfolgen.

public:     // User declarations
    void GetDepartmentEmployees(const System::String ADEPTNO);

Dieser Code muss in die Datei ClientUnit.cpp eingefügt werden.

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);
    }
}

Implementieren Sie das Ereignis OnChange der TListView, um die Prozedur GetDepartmentEmployees aufzurufen.

void __fastcall TForm2::ListViewDepartmentsChange(TObject *Sender)
{
    // Show department/employee details
    System::String LDEPTNO = ((TListViewItem*)(ListViewDepartments->Selected))->Detail;
    GetDepartmentEmployees(LDEPTNO);

}

Prozedur "ApplyUpdates"

Die in "FDMemTableDepartment" und "FDMemTableEmployee" gespeicherten Daten können über die Benutzeroberfläche geändert werden. Wenn der Benutzer auf die Schaltfläche "Apply Updates" klickt, werden mit dem folgenden Code Aktualisierungen zurück an den Server gesendet.

  • In Delphi:

Zuerst müssen Sie eine Funktion erstellen, um TFDJSONDeltas abzurufen:

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;

Erstellen Sie jetzt die Methode zur Übernahme der Änderungen:

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;

Implementieren Sie das Ereignis OnClick, um die Prozedur ApplyUpdates aufzurufen.

procedure TForm2.ButtonApplyUpdatesClick(Sender: TObject);
begin
  ApplyUpdates;
end;
  • In C++:

Die Deklaration der Methode muss in der Datei ClientUnit.h erfolgen.

public:     // User declarations
    void ApplyUpdates();

Dieser Code muss in die Datei ClientUnit.cpp eingefügt werden.

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);

}

Implementieren Sie das Ereignis OnClick, um die Prozedur ApplyUpdates aufzurufen.

void __fastcall TForm2::Button2Click(TObject *Sender)
{
    ApplyUpdates();
}

Siehe auch