AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Programm-Aufbau bei asynchronem DB-zugriff

Ein Thema von Ykcim · begonnen am 26. Nov 2019 · letzter Beitrag vom 29. Nov 2019
Antwort Antwort
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#1

Programm-Aufbau bei asynchronem DB-zugriff

  Alt 26. Nov 2019, 11:27
Hallo Zusammen,
ich versuche gerade meine erste Client/Server Web-Anwendung in Delphi zu erstellen. Ich nutze dazu die Komponenten von TMS (XDATA und WebCore). Aber ich glaube, meine Frage hat nichts mit den Komponenten zu tun…
Ich hoffe, ich kann das Problem und den Aufbau halbwegs verständlich erklären…

Ich ein Form (Form_NMain), dass bei Start der Anwendung erstellt wird.
Im Create wird ein Daten_Form erstellt, dass alle Datenbank-Komponenten enthält (Connection, DataSet, DataSource)

Delphi-Quellcode:
procedure TForm_NMain.WebFormCreate(Sender: TObject);
begin
   if not Assigned(Data_Module) then begin
      Data_Module := TData_Module.Create(Form_NMain);
   end;
end;

procedure TData_Module.WebFormCreate(Sender: TObject);
begin
   if not xConnection.Connected then begin
      if not xConnection_connect then begin
         Showmessage('Es gibt Probleme mit der Verbindung zum DB-Server.');
         Exit;
      end;
   end;
end;

function TData_Module.xConnection_connect: boolean;
   procedure OnConnect;
   begin
      Result:= true;
   end;
   procedure OnError(Error: TXDataWebConnectionError);
   begin
      ShowMessage('XData server connection failed with error: ' +
      Error.ErrorMessage);
      Result:= false;
   end;
begin
   if xConnection.Connected then
      Result:= true
   else
      xConnection.Open(@OnConnect, @OnError);
end;

Im Form_NMain.onShow wird noch eine LogIn-Page erstellt
Delphi-Quellcode:
procedure TForm_NMain.WebFormShow(Sender: TObject);
begin
   Create_frmLogIn;
end;

procedure TForm_NMain.Create_frmLogIn;
begin
   Frame_Control.TabIndex:=0;
   if not Assigned(Form_LogIn) then begin
      Form_LogIn := TForm_LogIn.CreateNew(Sheet_LogIn.ElementID, nil);
   end;
end;
Jetzt sollen die Labels auf der LogIn-Page aus Werten aus der Datenbank bestückt werden.
Delphi-Quellcode:
procedure TForm_LogIn.WebFormCreate(Sender: TObject);
begin
   if Data_Module.xConnection_connect then begin
      Data_Module.Get_Sprache;
      Label_LoginTitel.DataSource:=Data_Module.DSC_Sprache;
      Label_LoginTitel.DataField:='login_Titel';
      Label_LogInUser.DataSource:=Data_Module.DSC_Sprache;
      Label_LogInUser.DataField:='login_lable_username';
      Label_LogInPasswort.DataSource:=Data_Module.DSC_Sprache;
      Label_LogInPasswort.DataField:='login_label_passwort';
   end;
end;
Get_Sprache holt mittels eines Services die Daten aus der Datenbank
Delphi-Quellcode:
procedure TData_Module.Get_Sprache;
   procedure OnResponse(Response: TXDataClientResponse);
   begin
      xDST_Sprache.Close;
      xDST_Sprache.SetJsonData(TJSArray(Response.Result));
      xDST_Sprache.Open;
   end;
begin
   if xConnection_connect then begin
      xClient.RawInvoke('IData_xChangeService.Get_Sprache',[], @OnResponse);
   end;
end;

So der aktuelle Programm-Aufbau und mein Versuch, mit asynchronem Datenbank-Zugriff umzugehen. Vorschläge und Verbesserungen sind sehr willkommen.

Mein Problem ist, dass auf xConnection irgendwie nicht zugegriffen werden kann. Ich bekomme im Chrome den Fehler: Uncaught TypeError: Cannot read property 'GetConnected' of undefined | TypeError: Cannot read property 'GetConnected' of undefined at Object.xConnection_connect (http://localhost:8000/NedCom_Web/NedCom_Web.js:44638:29) at Object.WebFormCreate (http://localhost:8000/NedCom_Web/NedCom_Web.js:95114:37) at Object.cb [as FOnCreate] (http://localhost:8000/NedCom_Web/NedCom_Web.js:222:26) at Object.DoFormLoad (http://localhost:8000/NedCom_Web/NedCom_Web.js:24758:64) at XMLHttpRequest.cb (http://localhost:8000/NedCom_Web/NedCom_Web.js:222:26)
at http://localhost:8000/NedCom_Web/NedCom_Web.js [44638:29]

Kann mir jemand helfen, einen funktionierende Programm-Aufbau für ein asynchrones Programm zu bekomme? Das die Daten vom Server korrekt bereitgestellt ist sichergestellt und definitiv nicht das Problem.

Vielen Dank
Patrick
Patrick

Geändert von Ykcim (26. Nov 2019 um 11:30 Uhr)
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 26. Nov 2019, 15:55
So, ich habe natürlich weiter probiert und gelesen und bin auf die Frage gestoßen, wann die CallBack Procedure ausgeführt wird und ob eine andere Funktion auf das Ergebnis wartet?

Delphi-Quellcode:
procedure TForm_LogIn.WebFormCreate(Sender: TObject);
begin
   if Data_Module.xConnection_connect then begin
      Data_Module.Get_Sprache;
      Label_LoginTitel.DataSource:=Data_Module.DSC_Sprache;
      Label_LoginTitel.DataField:='login_Titel';
      Label_LogInUser.DataSource:=Data_Module.DSC_Sprache;
      Label_LogInUser.DataField:='login_lable_username';
      Label_LogInPasswort.DataSource:=Data_Module.DSC_Sprache;
      Label_LogInPasswort.DataField:='login_label_passwort';
   end;
end;
Hier rufe ich als erstes die Funktion xConnection_connect auf, die ein booloean als Result hat.

Delphi-Quellcode:
function TData_Module.xConnection_connect: boolean;
   procedure OnConnect;
   begin
      Result:= true;
   end;
   procedure OnError(Error: TXDataWebConnectionError);
   begin
      Result:= false;
      ShowMessage('XData server connection failed with error: ' +
      Error.ErrorMessage);
   end;
begin
   Result:= false;
   if xConnection.Connected then begin
      Result:= true;
   end
   else begin
      xConnection.Open(@OnConnect, @OnError);
   end;
end;
In dieser Funktion prüfe ich ab, ob die Connection eine Verbindung hat oder nicht. if xConnection.Connected
Wenn nicht soll sie hergestellt werden. xConnection.Open(@OnConnect, @OnError);
In den CallBacks wird dann der Result-Wert der Function xConnection_connect gesetzt.
Delphi-Quellcode:
procedure OnConnect;
   begin
      Result:= true;
   end;
Delphi-Quellcode:
procedure OnError(Error: TXDataWebConnectionError);
   begin
      Result:= false;
      ShowMessage('XData server connection failed with error: ' +
      Error.ErrorMessage);
   end;
Da die CallBacks ja erst im Falle einer Antwort seitens der xConnection aufgerufen werden, dachte ich, dass ich meine Anwendung solange "anhalte". Ist das so? Bleibt die Anwendung in der procedure TForm_LogIn.WebFormCreate(Sender: TObject); stehen, bis der Result-Wert von Data_Module.xConnection_Connect kommt?

Vielen Dank
Patrick
Patrick

Geändert von Ykcim (26. Nov 2019 um 15:57 Uhr)
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.809 Beiträge
 
Delphi 12 Athens
 
#3

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 26. Nov 2019, 18:02
Kennst du CodeSite?
Das kannst du in der Standardedition kostenlos via GetIt installieren und
hast dann ein ganz nettes Logging tool.

Dann kannst du Log-Meldungen in deine Events einbauen und damit schauen in
welcher Reihenfolge die Ausgelöst werden.
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 27. Nov 2019, 10:54
Hallo TurboMagic,

nein, dass Logging Tool kenne ich noch nicht. Ich werde mich mal damit beschäftigen. Danke!

Hast Du eine Idee, wie ich bei einer WebApplication so etwas wie Application.ProcessMessages realisieren kann? Gibt es dafür eine Alternative? Denn bei meinem Projekt bekomme ich die Error-Meldung: [Fehler] TLogicUnit.pas(29): identifier not found "ProcessMessages"

Ich möchte erreichen, dass die Applikation ein paar Sekunden wartet, bis die Rückmeldung von der Connection kommt, ob sie sich verbunden hat, oder nicht...

Vielen Dank

Patrick
Patrick
  Mit Zitat antworten Zitat
Edelfix

Registriert seit: 6. Feb 2015
Ort: Stadtoldendorf
213 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 27. Nov 2019, 11:07
Eventuell eine Connecting Form vor der LogIn-Page anzeigen und die LogIn-Page erst anzeigen wenn alle werte für die LogIn-Page da sind.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 27. Nov 2019, 21:02
Ich möchte erreichen, dass die Applikation ein paar Sekunden wartet, bis die Rückmeldung von der Connection kommt, ob sie sich verbunden hat, oder nicht...
Warum willst Du warten, wenn Du eine asynchrone Kommunikation willst?

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Neumann

Registriert seit: 6. Feb 2006
Ort: Moers
529 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 27. Nov 2019, 21:19
Wenn man ein TXDataWebDataset verwendet, braucht man es nur mit load öffnen (die Connection öffnet dann automatisch mit). Dann einfach den Event AfterOpen nutzen, der feuert wenn die Daten übertragen sind.

Mehr Aufwand ist nicht nötig.
Ralf
Gruß vom Niederrhein
  Mit Zitat antworten Zitat
Neumann

Registriert seit: 6. Feb 2006
Ort: Moers
529 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 27. Nov 2019, 21:23
Ergänzung: Es gibt ein paar Videos von TMS auf Youtube, wo das Ganze gut erklärt wird. Hat mir geholfen als ich mit Webcore und XData angefangen habe.
Ralf
Gruß vom Niederrhein
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Programm-Aufbau bei asynchronem DB-zugriff

  Alt 29. Nov 2019, 08:22
Vielen Dank!

Ich bin neu in der asynchrone Kommunikation und tue mich damit noch echt schwer...
Die Videos sind bei mir alle in den Lesezeichen, weil ich sie mir sooft ansehe...

Der Support von TMS hat mich in einem anderen Thema unterstützt, was aber die gleich Ursache hatte. Ich muss einfach lernen, andersherum zu denken. Bis jetzt waren bei meinen Programmen die Daten immer sofort da. Jetzt muss ich auf sie warten.

Aber man bekommt automatisch viele Verschachtlungen, oder?

Ich habe es jetzt so gelöst:

Delphi-Quellcode:
procedure TForm_NMain.WebFormShow(Sender: TObject);
begin
   Create_frmLogIn;
end;

procedure TForm_NMain.Create_frmLogIn;
begin
   Frame_Control.TabIndex:=0;
   if not Assigned(Form_LogIn) then begin
      Form_LogIn := TForm_LogIn.CreateNew(Sheet_LogIn.ElementID, nil);
      Form_LogIn.OnLogIn_Run:=Run_LogIn;
      Data_Module.xConnection_connect(procedure
         begin
            Data_Module.Get_Sprache(Design.Design_LogIn);
         end
         );
   end;
end;


//in TDataUnit
type
   TConnectCallback = reference to procedure;
   TDataRecievedCallback = reference to procedure;


procedure TData_Module.xConnection_connect (AOnConnect: TConnectCallback);
   procedure OnConnect;
   begin
      if Assigned(AOnConnect) then AOnConnect();
   end;
   procedure OnError(Error: TXDataWebConnectionError);
   begin
      ShowMessage('XData server connection failed with error: ' +
      Error.ErrorMessage);
   end;
begin
   if xConnection.Connected then begin
      if Assigned(AOnConnect) then AOnConnect();
   end
   else begin
      xConnection.Open(@OnConnect, @OnError);
   end;
end;

procedure TData_Module.Get_Sprache(AOnDataRecieved: TDataRecievedCallback);
   procedure OnResponse(Response: TXDataClientResponse);
   begin
      xDST_Sprache.Close;
      {xDST_Sprache_SetFields;}
      xDST_Sprache.SetJsonData(TJSArray(Response.Result));
      xDST_Sprache.Open;
      if Assigned(AOnDataRecieved) then AOnDataRecieved();
   end;
begin
   xClient.RawInvoke('IData_xChangeService.Get_Sprache',[], @OnResponse);
end;

Damit klappt es jetzt gut. Aber wenn jemand noch Verbesserungen und Vereinfachungen sieht, bin ich für Lernunterstützung immer dankbar!

Ich habe allerdings {xDST_Sprache_SetFields; auskommentiert, weil ich die Felder des DataSet noch nicht zur Laufzeit erstellt bekomme.

Delphi-Quellcode:
procedure TData_Module.xDST_Sprache_SetFields;
begin
   xDST_Sprache.Fields.Clear;
   with xDST_Sprache.FieldDefs do begin
      Add('sprache_id', ftInteger, 0, false);
      Add('sprache', ftString, 45, false);
      Add('login_Titel', ftString, 45, false);
      Add('login_label_username', ftString, 45, false);
      Add('ftString', ftString, 45, false);
      Add('login_btn_login', ftString, 45, false);
      Add('login_btn_abbruch', ftString, 45, false);
      Add('uebersicht_titel', ftString, 45, false);
      Add('grid_schnellsuche', ftString, 45, false);
   end;
end;
Da kommt dann immer der Fehler
Zitat:
fMessage::EntitySetName not specified.
Den EntitySetNamen setze ich nicht, weil ich das DataSet ja manuell bestücke...
Hat da jemand eine Idee, wie ich das korrekt machen muss?

Vielen Dank
Patrick
Patrick

Geändert von Ykcim (29. Nov 2019 um 08:27 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:15 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz