Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi FireDAC Merkwürdigkeiten (https://www.delphipraxis.net/207965-firedac-merkwuerdigkeiten.html)

haentschman 21. Mai 2021 10:05

Datenbank: MSSQL • Version: 2017 • Zugriff über: FireDAC

FireDAC Merkwürdigkeiten
 
Hallöle...

Wieder was zum Schmunzeln...oder auch nicht. :shock:

Wie geht das?
Zitat:

compiled with : Delphi 10.1 Berlin
madExcept version : 5.1.0
callstack crc : $172ecbca, $cf2706b0, $b3928f31
exception number : 1
exception class : EDatabaseError
exception message : FDQery: Datenmenge weder im Editier- noch im Einfügemodus.

thread $47e8:
00789565 +0c9 SEAM.exe Data.DB 3268 +7 DatabaseError
007a05e5 +035 SEAM.exe Data.DB 13661 +1 TDataSet.UpdateRecord
007a163a +006 SEAM.exe Data.DB 14364 +1 TDataSet.Post
0082826d +029 SEAM.exe FireDAC.Comp.DataSet 5006 +6 TFDDataSet.Post
036895f0 +0cc SEAM.exe DMEdit 4034 +7 TDM.FillLastEmployee
036a46d9 +0c1 SEAM.exe DMEdit 7242 +6 TDM.FDQTerminAfterPost
007a273d +015 SEAM.exe Data.DB 15019 +1 TDataSet.DoAfterPost
007a16a9 +075 SEAM.exe Data.DB 14374 +11 TDataSet.Post
0082826d +029 SEAM.exe FireDAC.Comp.DataSet 5006 +6 TFDDataSet.Post
007a247d +041 SEAM.exe Data.DB 14901 +7 TDataSet.CheckBrowseMode
Delphi-Quellcode:
procedure TDM.FillLastEmployee(ID: Integer; Employee, TerminDate: string);
begin
  FDQuery.Locate('idBelKopf', ID, []);
  if FDQuery.State = dsBrowse then
  begin
    FDQuery.Edit;
    FDQuery.FieldByName('Monteur').AsString := Employee;
    FDQuery.FieldByName('MonPlan').AsString := TerminDate;
    FDQuery.Post; // <- Zeile 4034
  end;
end;

Delphi.Narium 21. Mai 2021 10:15

AW: FireDAC Merkwürdigkeiten
 
Datenbankverbindung ist ReadOnly, FDQuery ist ReadOnly oder enthält eine nicht editierbare Datenmenge (z. B: eine Select über mehrere Tabellen), ...?

haentschman 21. Mai 2021 10:37

AW: FireDAC Merkwürdigkeiten
 
Zitat:

Datenbankverbindung ist ReadOnly, FDQuery ist ReadOnly oder enthält eine nicht editierbare Datenmenge (z. B: eine Select über mehrere Tabellen), ...?
PS: das funktioniert 100x am Tag :zwinker:

ReadOnly: False
QueryReadOnly: False
Join: no

Wir haben teilweise richtige Netzwerkprobleme...kann das damit zusammenhängen?

Delphi.Narium 21. Mai 2021 10:40

AW: FireDAC Merkwürdigkeiten
 
Ja!

Verbindung geht zwischendurch flöten, der Server merkt es und die Datenbank macht ein Rollback.

Beim Post gibt es dann eine neue Datenbankverbindung, eine neu Transaktion und das Zusammenspiel passt nicht mehr.

Strubbel in beliebiger Kombination ist in so 'nem Fall möglich.

TurboMagic 22. Mai 2021 16:07

AW: FireDAC Merkwürdigkeiten
 
Und wie geht man mit sowas um?

Delphi.Narium 22. Mai 2021 16:40

AW: FireDAC Merkwürdigkeiten
 
Für eine stabile Netzwerkverbindung sorgen.

Ggfls. TimeOut-Einstellungen auf beiden Seiten anpassen.

Ursachenforschung betreiben:

Z. B. per Ping prüfen, wie die Antwortzeiten zwischen Client und Server sind.
"Unnormal hoch"? Ursache suchen und beseitigen.

Per Traceroute prüfen, ob eventuell ein Problem "irgendwo auf der Strecke zwischen Client und Server" vorliegt. Router und oder Switch zicken rum, sind (halbwegs) defekt, Kabelstecker locker, Wackelkontakt durch Kabelbruch, ...

Prüfen, ob es ausschließlich Probleme bei der Kommunikation zwischen Datenbankserver und Datenbankclient sind, oder eher grundsätzliche Probleme vorliegen.

Eigentlich gibt es da auf technischer Ebene eine Unmenge an Problemen, die man als Entwickler eher nicht beeinflussen kann. Da müssen dann die entsprechenden Admins und / oder Techniker ran.

Im Programm dafür sorgen, dass auch bei solchen Problemen ein konsistenter Datenbestand sichergestellt ist.

Reparaturroutinen à la: Klapptnicht, dann einfach nochmal probieren, nur dann, wenn es wirklich keine andere Lösungsmöglichkeit gibt. Aber das ist eher nicht empfehlenswert, insbesondere nicht bei Datenbanken, bei HTTP- oder FTP-Abfragen, lesen von Dateien "irgendwo auf 'nem Netzlaufwerk", ... kann man sowas eventuell machen.

jobo 22. Mai 2021 18:43

AW: FireDAC Merkwürdigkeiten
 
Soll es so sein, dass nur auf DSBrowse (und kein anderer State) geprüft wird?
Und wenn schon kein anderer State in Frage kommt, dann keine Fehlerbehandlung wenn die erwarteten nicht vorliegen? (Dann wird die Speicherroutine einfach so beendet, ohne das getan zu haben, was sie soll?)
Das Locate ist eine Funktion, ob es geklappt hat oder gerade die Connection flöten geht oder was anderes, interessiert die nachfolgende Operation auch nicht. Es wird also vielleicht woanders eingetragen, was zu der nicht gefundenen ID gehört.
Wenn man tatsächlich instabile DB Connection hat, könnte das zu unerwarteten Ergebnissen führen. Vielleicht sogar mit stabiler Connection.

Delphi.Narium 22. Mai 2021 18:54

AW: FireDAC Merkwürdigkeiten
 
Sagen wir mal so: Die Routine ist verbesserungswürdig:
Delphi-Quellcode:
procedure TDM.FillLastEmployee(ID: Integer; Employee, TerminDate: string);
begin
  // Suche den Satz mit der ID
  FDQuery.Locate('idBelKopf', ID, []); // Gefunden = true, nicht gefunden = false.
  // Aber das interessiert uns nicht.
  // Sind wir im Browsemodus, dann
  if FDQuery.State = dsBrowse then
  begin
    // wird der Satz geändert, auf dem wir gerade mit dem Datensatzzeiger stehen.
    // Es kann der Satz mit idBelKopf = ID sein, muss es aber nicht.
    FDQuery.Edit;
    FDQuery.FieldByName('Monteur').AsString := Employee;
    FDQuery.FieldByName('MonPlan').AsString := TerminDate;
    try
      FDQuery.Post; // <- Zeile 4034
    on e : exception do begin
      FDQuery.Cancel;
      // Und hier dann eine anwenderfreundliche Fehlerbehandlung oder Fehlermeldung ausgeben.
    end;
  end;
end;

Uwe Raabe 22. Mai 2021 22:21

AW: FireDAC Merkwürdigkeiten
 
Das Locate erzwingt immer den Browse-Mode (zumindest bei FireDAC). Wenn das Locate keinen anderen Zweck erfüllt, kannst du auch gleich CheckBrowseMode aufrufen und die Prüfung auf Browse-Mode weglassen.

Welcher Datensatz dann geändert wird (und es wird immer einer geändert, wenn keine Exception oder ähnliches auftritt) hängt vom Rückgabewert von Locate ab. Entweder ist es der Datensatz, der gesucht wurde oder der Datensatz der vor dem Locate aktiv war.

Man sollte noch erwähnen, dass bei einem leeren DataSet das Edit intern ein Insert ausführt.

jobo 23. Mai 2021 12:49

AW: FireDAC Merkwürdigkeiten
 
Die Problematik scheint ja vielleicht in der instabilen Connection zu liegen und dann ist das was 100x funktioniert eben nicht in jedem Fall geeignet.

Dank Outsourcing hat man ja heute wohl häufiger mit entfernten DB zu tun, die über VPN Tunnel o.ä. angesprochen werden. Hier geht es dann los mit Latenzen und der "kleinteiligen" Kommunikation, die offenbar eher für's LAN gemacht/geeignet ist.

Delphi.Narium hat ja schon ähnliche Fragen in den Code kommentiert. Ich bin lange nicht mehr auf dem aktuellen Stand bei Delphi, aber würde bspw. unter den genannten Umständen auch die verlässliche Funktion eines Dataset.edit in Frage stellen. Das bräuchte dann u.U. auch schon ein Exception Handling, ich vermute zumindest, dass dahinter die Datenbanksperren geregelt werden.
Unabhängig von der Stabilität der Verbindung oder möglichen anderen Problemen, scheint mir das Ignorieren der Locate Rückgabe suboptimal zu sein.

Und wenn aus dem Update (Edit) ein Insert wird, weil gar nichts da ist, muss das ja auch noch lange nicht funktionieren, wenn die restlichen Felder (hier sind es ja nur 2 Nutzdaten) nicht den DB Regeln entsprechen. Dann scheitert es mindestens an der Relationslogik oder aber an DB Constraints (sofern vorhanden).

haentschman 24. Mai 2021 07:54

AW: FireDAC Merkwürdigkeiten
 
Moin...:P

Interessant, das man Probleme findet, die so niemals in den Kopf kamen...:P
Zitat:

Soll es so sein, dass nur auf DSBrowse (und kein anderer State) geprüft wird?
Zitat:

scheint mir das Ignorieren der Locate Rückgabe suboptimal zu sein
Zitat:

Für eine stabile Netzwerkverbindung sorgen.
Zitat:

Dann scheitert es mindestens an der Relationslogik oder aber an DB Constraints
...die Zeilen stammen aus der alten Codebasis. Ich konnte mich leider noch nicht darum kümmern. :? Das sieht man an dem vorhandenem Locate. :kotz:
Unabhängig davon ist mir ehrlich gesagt das mit der nicht behandelten Funktionsrückgabe nicht aufgefallen...:oops: Es wird später alles auf Objekte und SQL umgebaut. Dann habe ich andere Probleme...:stupid:

Ihr braucht nicht mehr die Ursache finden...es gibt wichtigere Baustellen.

Danke. :wink:

jobo 24. Mai 2021 14:54

AW: FireDAC Merkwürdigkeiten
 
Ich finde jetzt Locate nicht so schlimm, richtig angewendet. Heute würde ich es nicht mehr nutzen, aber hab ich mal, vor 20 Jahren. Das ist ja eigentlich eine der guten Seiten an Delphi, seine Kompatibilität/Beständigkeit.
Du gehst ja mit deinem eigenen Objekt und Storage Layer andere Wege, geht halt auch.
Aber es geht für mich an den mächtigen DB Features von Delphi vorbei. Alles da, was man braucht.

haentschman 25. Mai 2021 07:56

AW: FireDAC Merkwürdigkeiten
 
Moin...:P
Zitat:

Ich finde jetzt Locate nicht so schlimm
Mit MSSQL hatte schon mehrfach meine Probleme. Sowohl in der alten Firma als auch jetzt. Das Locate kam False zurück obwohl der Datensatz definitiv vorhanden war. :roll:
Deshalb schmeiße ich die raus...

Uwe Raabe 25. Mai 2021 09:08

AW: FireDAC Merkwürdigkeiten
 
Zitat:

Zitat von haentschman (Beitrag 1490060)
Mit MSSQL hatte schon mehrfach meine Probleme. Sowohl in der alten Firma als auch jetzt. Das Locate kam False zurück obwohl der Datensatz definitiv vorhanden war. :roll:
Deshalb schmeiße ich die raus...

Na ja, auch eine Art der Fehlerbeseitigung.

Wobei ich Locate schon immer (BDE, dbExpress, FireDAC) und mit verschiedenen Datenbanken ohne Probleme genutzt habe und das auch jetzt noch tue. Eine inhärente Fehlfunktion würde ich daher eher ausschließen.

jobo 25. Mai 2021 18:17

AW: FireDAC Merkwürdigkeiten
 
Zitat:

Zitat von haentschman (Beitrag 1490060)
Moin...:P
Zitat:

Ich finde jetzt Locate nicht so schlimm
Mit MSSQL hatte schon mehrfach meine Probleme. Sowohl in der alten Firma als auch jetzt. Das Locate kam False zurück obwohl der Datensatz definitiv vorhanden war. :roll:
Deshalb schmeiße ich die raus...

Mmh, solche pauschalen Aussagen sind leider schwer nachvollziehbar, dient schlimmstenfalls der Legendenbildung.
Es gibt ja noch ein paar Optionen für Locate und die Kombination mit Filter. Da kann schon was schief gehen beim Coden.
Es gab auch mal in bestimmten Fällen einen Bug bei zeitgleich gesetzten Filtern, was aber eher den umgekehrten Effekt hatte den Du beschreibst, es gab True zurück, obwohl der Datensatz außerhalb der Filtermenge lag.
Würde mich da eher Uwe anschließen.

haentschman 26. Mai 2021 06:05

AW: FireDAC Merkwürdigkeiten
 
Zitat:

Mmh, solche pauschalen Aussagen sind leider schwer nachvollziehbar
... kann ich jetzt nicht beweisen. Aber es gab damals mehrere Zeugen...mit offenen Augen. :P

PS: wir reden über MSSQL!
damals:
1. Vor dem Locate in die Query geguckt (Grid auf die Form...gefiltert oder nicht) -> Datensatz vorhanden!
2. Query.Locate -> False
...Logic im Ar...:roll:

Erklären kann ich das nicht. Damals war es ADO. Aber bei FireDAC habe ich es einmal auch gesehen. Imho tritt das nicht grundsätzlich auf. Ich habe nie herausgefunden welche Konstellation schief gelaufen ist. :? Vieleicht ist MSSQL das Problem. :gruebel:

Nach Umbau auf ein "select" gab es nie wieder Probleme.

Jetzt reden wir nicht mehr darüber...:wink:

Frickler 26. Mai 2021 08:55

AW: FireDAC Merkwürdigkeiten
 
Zitat:

Zitat von jobo (Beitrag 1490001)
Ich finde jetzt Locate nicht so schlimm, richtig angewendet. Heute würde ich es nicht mehr nutzen, aber hab ich mal, vor 20 Jahren. Das ist ja eigentlich eine der guten Seiten an Delphi, seine Kompatibilität/Beständigkeit.

Eine ständig offene Query, in der man per Locate, Edit und Post rumhampelt, hat schon was von TTable...

Ich würde so ein Konstrukt einfach durch eine UPDATE Anweisung ersetzen oder noch besser einen SP-Aufruf, der die eigentliche Datenbankstruktur verbirgt.

DasWolf 26. Mai 2021 12:45

AW: FireDAC Merkwürdigkeiten
 
Probleme beim
Delphi-Quellcode:
Locate
gibt es, wenn Felder in der Datenbank als CHAR oder NCHAR mit einer Länge > 1 definiert sind
und zusätzlich in der FDConnection die Eigenschaft
Delphi-Quellcode:
FormatOptions.StrsTrim
auf False gesetzt ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:50 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