1.8 führt Code vor Form.Create aus

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.
Antworten
Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

1.8 führt Code vor Form.Create aus

Beitrag von gladio »

Ich teste gerade einige meiner Programme auf 1.8RC3

Auf einem THauptForm liegt eine (mehrere) Datenkomponente (Zeos).
Diese ist im Entwurf und bei Programmstart inaktiv.
Aktiviert (active:=true) wird erst in der OnCreate-Procedure gesetzt.

Code: Alles auswählen

procedure THaupt.FormCreate(Sender: TObject);
begin
  ZQueryEinnahmen.Active := true;
  ZQueryAusgaben.Active := true;
  ZQueryKb.Active:=true;
  ZQueryKb.Open;
end

Das funktioniert in den 1.6x Versionen alles klaglos.
Mit 1.8 bricht die Programmausführung gleich bein Start ab:
..EDatabaseError... inactive dataset...

Code: Alles auswählen

procedure THaupt.DateEdit1Change(Sender: TObject);
begin
  .....
  ZQueryKb.active:=true//jetzt eingefügt, bringt nichts
 
  //Kassenbuch neu lesen
  with ZQueryKb do
  begin
    Close;
    SQL.Text:= 'Select * from Kassenbuch '
    +'where Datum = (:Arbeitsdatum) order by ID'  ;
    ParamByName('Arbeitsdatum').AsDate := Arbeitsdatum;
    ExecSQL;
    open;
    Last;  //hier Programmabbruch weil Dataset noch inaktiv ist
  end;
.....
end;
 

Diese Procedure (und auch andere) werden jetzt vor der FormCreate ausgeführt
also bei inaktiver Dataset, der Fehler also formal logisch.
Ist das so gewollt?

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: 1.8 führt Code vor Form.Create aus

Beitrag von wp_xyz »

Warum steht da ExecSQL? Ich dachte, immer das ist für INSERT/UPDATE/DELETE-Queries? Queries, die Datensätze zurückliefern (SELECT), musst du einfach nur öffnen (oder auf Active=true setzen - beides macht dasselbe, d.h. ZQueryKb.Open kannst du dir in FormCreate sparen, weil unmittelbar vorher schon ZQueryKB.Active := true gesetzt wurde).

Dass TDBEdit.OnChange vor TForm.OnCreate aufgerufen wird, erscheint mir normal. Denn vor TForm.OnCreate werden alle Controls mit ihren Properties aus der lfm-Datei gelesen, und beim Setzen der Properties kann dann je nach Property OnChange gefeuert werden. Versuche mal an den Anfang des OnChange-Handlers ein "if csLoading in ComponentState then exit" zu setzen.

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: 1.8 führt Code vor Form.Create aus

Beitrag von gladio »

wp_xyz hat geschrieben:Warum steht da ExecSQL? Ich dachte, immer das ist für INSERT/UPDATE/DELETE-Queries? Queries, die Datensätze zurückliefern (SELECT), musst du einfach nur öffnen (oder auf Active=true setzen - beides macht dasselbe, d.h. ZQueryKb.Open kannst du dir in FormCreate sparen, weil unmittelbar vorher schon ZQueryKB.Active := true gesetzt wurde).

Das stimmt natürlich. Das Eine (.open) ist jetzt mit reingerutscht und das ExecSQL ist nicht notwendig.
Beides ist aber unschädlich und für die Fehlersituation nicht relevant.

wp_xyz hat geschrieben:Dass TDBEdit.OnChange vor TForm.OnCreate aufgerufen wird, erscheint mir normal. Denn vor TForm.OnCreate werden alle Controls mit ihren Properties aus der lfm-Datei gelesen, und beim Setzen der Properties kann dann je nach Property OnChange gefeuert werden. Versuche mal an den Anfang des OnChange-Handlers ein "if csLoading in ComponentState then exit" zu setzen.

Das OnChange ist nicht in einem DBEdit sondern in einem DateEdit (Datumpicker).

Kommentiere ich die Fehlerstelle aus (Last) bricht das Programm in der nächsten Procedure ab, wenn wieder auf eine Datenmenge zugegriffen wird usw.

Wie bereits geschrieben: mit Lazarus 1.6 gibt es kein Gemecker.

Das mit 'csLoading' würde ich später testen, hab jetzt hier keine 1.8-Installation.
Das müßte dann vermutlich in fast jede Procedure.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: 1.8 führt Code vor Form.Create aus

Beitrag von wp_xyz »

gladio hat geschrieben:Das OnChange ist nicht in einem DBEdit sondern in einem DateEdit (Datumpicker).

Das beigefügte Mini-Projekt enthält ein DateEdit, ein normales Edit und eine Combobox, deren OnChange-Events jeweils eine Meldung in ein Memo schreiben (genauso wie das Formular selbst). Man sieht daran, dass DateEdit.OnChange immer vor Form.OnCreate kommt (TEdit und TCombobox erzeugen anscheinend kein OnChange während des Einlesens). Lasse ich das Programm mit Laz 1.6.4 statt mit Laz trunk/1.8RC3 laufen, sehe ich exakt dasselbe Verhalten.

Aber eigentlich ist das egal. Das Problem ist, dass das DateEdit nichts über die Datenbank weiß, und du kannst nicht davon ausgehen, dass die Datenbank bereit ist, wenn das DateEdit sich ändert. Es ist reiner Zufall, dass das Problem nicht schon früher aufgetreten ist. Statt, wie früher vorgeschlagen "csLoading in ComponentState" abzufragen (was nicht funktioniert wird, wie das Demo-Projekt zeigt), solltest du prüfen, ob die Datenbankverbindung besteht (if not ZConnection1.Connected then exit).

Wenn du in meinem Demoprojekt etwas ins DateEdit eintippst, siehst du ein weiteres Problem: mit jedem Tastendruck wird OnChange ausgelöst, beim Verlassen des Controls ein weiteres Mal. Da jedes OnChange bei dir die Abfrage neu ausführt, denke ich nicht, dass das erwünscht ist. Wahrscheinlich ist OnEditingDone besser geeignet.
Dateianhänge
OnChangeBeforeOnCreate.zip
(2.07 KiB) 136-mal heruntergeladen

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: 1.8 führt Code vor Form.Create aus

Beitrag von gladio »

Die Prüfung mit

Code: Alles auswählen

if not ZConnection1.Connected then exit;

funktioniert nicht.
Überraschenderweise besteht die Connection, somit kein 'exit'.
Aber
das ist die richtige Richtung.
Ich habe stattdessen

Code: Alles auswählen

procedure THaupt.DateEdit1Change(Sender: TObject);
begin
  if not ZQueryKB.active then exit; //1.8
....
end;

genommen. Das ist es.

OnEditingDone habe ich kurz angetestet (die OnChange umgeleitet)
Wird auf jeden Fall nicht so oft durchlaufen, benötigt aber ein 'Enter' als Eingabeabschluß.
Die Direkteigabe ist aber nicht erwünscht.
Erstmal lasse ich es beim OnChange.

Danke
Gruß Andreas

Antworten