Einzelnen Beitrag anzeigen

Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.095 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Firedac als JSON ohne Feldbezeichner exportieren

  Alt 23. Apr 2023, 20:35
Hallo Uwe,

ich verwende die MARS Komponenten von Andre Magni und stelle damit einen REST-API Server bereit. Ich habe also keine Control die an der Query gebunden sind.

Um alle Personen abzurufen, nutze ich die Methode etwa so:


Delphi-Quellcode:
function TApiResource.GetPersonen: TFDQuery;
begin
  result :=FD.Query(' SELECT * FROM PERSONEN ');
end;
als Result bekommen ich:

Code:
{"RecordSet" : [
   {
      "PERSONID" : 295,
      "NAMEN" : "Brandl",
      "TITEL" : null,
      "VORNAME" : "Carmen",
      "GEBURTSDATUM" : "29.08.1994",
      "PERSONALNR" : "10115854",
      "EINTRITTJAHR" : 0,
      "FACHNR" : 101006,
      "FACH" : "SV45HD",
   },
...
Die Datenmenge ist relativ groß mit ca. 500.000 Records und es werden viel mehr Felder ausgegeben als hier im Beispiel.
Die Datenmenge kann ich übrigens nicht auf einmal exportieren da der Speicher nicht ausreicht. Die Feldbezeichner machen den größten Anteil aus und die wiederholen sich bei jedem Record.

Jetzt dache ich, ich durchlaufe die Query und exportiere die Daten ohne die Feldbezeichner einfach als Array von Werten.


Delphi-Quellcode:
function TApiResource.GetPersonen: TJSONArray;
var LPersonen, LPersonenRec: TJSONArray;
    qrPersonen: TFDQuery;
begin
  LPersonen := TJSONArray.Create;

  qrPersonen := FD.CreateQuery('');
  qrPersonen.open;


  while not qrPersonen.eof do
  begin
    LPersonenRec := TJSONArray.Create;
    LPersonenRec.add(qrPersonen.FieldByName('PERSONID').AsLargeInt);
    LPersonenRec.add(qrPersonen.FieldByName('NAMEN').AsString);
    LPersonenRec.add(qrPersonen.FieldByName('TITEL').AsString);
    LPersonenRec.add(qrPersonen.FieldByName('VORNAME').AsString);
    LPersonenRec.add(qrPersonen.FieldByName('GEBURTSDATUM').AsString);
    LPersonenRec.add(qrPersonen.FieldByName('PERSONALNR').AsString);
    LPersonenRec.add(qrPersonen.FieldByName('EINTRITTJAHR').AsInteger);
    LPersonenRec.add(qrPersonen.FieldByName('FACHNR').AsLargeInt);
    LPersonenRec.add(qrPersonen.FieldByName('FACH').AsString);

    LPersonen.Add(LPersonenRec);

    qrPersonen.next;
  end;

  result := LPersonen;

end;
Dieser Vorgang dauert jedoch deutlich länger als wenn ich das TFDQuery direkt ausgebe.

Wenn ich die Methode umbaue auch
Code:
SELECT FIRST 10000 SKIP 10000 *...
dann dauert es insgesamt noch länger da das vorbereiten der Query erneut durchgeführt wird für alle 10000 Records. Die Query ist in dem Beispiel ohne Where und joins. Ich Wirklichkeit ist die Query also komplexer.

Dann dachte ich, ich erzeuge eben bei einer Anfrage eine JSON in einem anonymen Thread und schreibe es in ein File. Über eine zweite Methode rufe ich dann das File als Stream ab. Das funktioniert leider auch nicht da ich innerhalb des anonymen Threads auf das FD Object FD.CreateQuery(''); nicht zugreifen kann. Wenn das gehen würde, wäre das perfekt da das File im Hintergrund erzeug werden würde und ich nur periodisch nach dem File frage könnte.
  Mit Zitat antworten Zitat