Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi FireDAC Async Fehler in der "Oberfläche" ? (https://www.delphipraxis.net/215189-firedac-async-fehler-der-oberflaeche.html)

haentschman 23. Mai 2024 11:45

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

FireDAC Async Fehler in der "Oberfläche" ?
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallöle...8-)

Ich habe eine Acync Query (Danke an Uwe). Das Laden der Artikel dauert normal ca. 10. Sekunden. Deshalb Async.
Funktioniert fast...:roll:

In meiner Entwicklungsumgebung (lokaler MSSQL) habe ich nur den Fehler im Anhang wenn ich zu schnell in der Oberfläche wechsle. :cry: Auf dem Server habe ich manchmal keine Datenmenge (wahrscheinlich unterdrückter Fehler) ... kommt später dran.

Ablauf:
1. beim Wechsel der Rechnung werden die Artikel, incl. der Kundenpreise, geladen. -> direkt RefreshArticle -> alles OK. Die Positionen stimmen, Datenmenge i.O.
2. Wechsel Rechnungsempfänger (nur (1) - Bild1) -> direkt RefreshArticle -> (kein (2) - Bild1) -> alles OK
3. Wechsel Rechnungsempfänger (nur (1) - Bild1) -> direkt RefreshArticle -> (direkt (2) - Bild1, während des Ladens im Hintergund) -> Fehler im Anhang

Wie kann ich den Fehler verhindern? :gruebel:

Code nach Beispiel Emba:
http://docwiki.embarcadero.com/RADSt...rung_(FireDAC)
Delphi-Quellcode:
function TSEAMDatabaseBase.CreateQueryAsync: TFDQuery;
begin
  Result := TFDQuery.Create(nil);
  Result.FetchOptions.Mode := fmAll;
  Result.ResourceOptions.CmdExecMode := amAsync;
  Result.Connection := FConnection;
  Result.OnError := DoOnQueryError;
end;
.
.
constructor TFormReceiptLogic.Create(Preferences: TSEAMPreferences);
begin
  FReproPartDataSet := DMZU.Database.CreateQueryAsync; // nur Instanz
  FReproPartDataSet.AfterOpen := DoArticleAfterOpen;
  FReproPartDataSet.BeforeOpen := DoArticleBeforeOpen;
...
end;
.
.
procedure TFormReceiptLogic.DoArticleBeforeOpen(DataSet: TDataSet);
begin
  DMLUP.dsReproPart.DataSet := nil;
end;

procedure TFormReceiptLogic.DoArticleAfterOpen(DataSet: TDataSet);
begin
  DMLUP.dsReproPart.DataSet := FReproPartDataSet;
  FIsRefreshing := False;
end;
.
.
procedure TFormReceiptLogic.RefreshArticle;
begin
  if (not FIsRefreshing) and (FReproPartDataSet.Command.State = csInactive) or (FReproPartDataSet.Command.State = csPrepared) then // nur Ausführen wenn nicht in Bearbeitung
  begin
    FIsRefreshing := True;
    DMZU.Database.FillDataSetRepositoryPart(FReproPartDataSet, FArticleFavorite, FReceiptAddress);
  end;
end;

Uwe Raabe 23. Mai 2024 13:22

AW: FireDAC Acync Fehler in der "Oberfläche" ?
 
Ist die if-Abfrage in RefreshArticle wirklich richtig?
Aufgrund der Operator-Precedence von AND before OR wird die Abfrage auch bei einem
Delphi-Quellcode:
FIsRefreshing = True
und
Delphi-Quellcode:
FReproPartDataSet.Command.State = csPrepared
wahr.

In solchen Fällen empfehle ich immer Klammern, also entweder um das AND oder um das OR.

haentschman 23. Mai 2024 13:50

AW: FireDAC Acync Fehler in der "Oberfläche" ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Recht hast du...8-) Geschuldet dem stundenlagen Probieren ohne Ergebnis. Da geht sowas schon Mal verloren. Ich wußte, daß das mit dem Threading zu tun hat. FIsRefreshing ist zusätzliches Flag vom Probieren. :zwinker:
Delphi-Quellcode:
if (not FIsRefreshing) and ((FReproPartDataSet.Command.State = csInactive) or (FReproPartDataSet.Command.State = csPrepared)) then
.
Das ändert leider nichts am Fehler...der kommt wieder wenn ich zu schnell bin. :?

Nachtrag:
Normalerweise arbeitet die Software mit dem "NativeClient2012". Was bitteschön hat da ODBC zu suchen? Macht die Query im Thread eine eigene Connection auf und nimmt sich den ersten Treiber im System?

Uwe Raabe 23. Mai 2024 16:04

AW: FireDAC Acync Fehler in der "Oberfläche" ?
 
Aus FireDAC.Phys.MSSQL.pas:
Delphi-Quellcode:
    ODBCDriver := FindBestDriver(
      {$IFDEF MSWINDOWS} [C_2018_ODBC, C_2017_ODBC, C_2012_NC, C_2016_ODBC, C_2012_ODBC, C_2008, C_2005, C_2000] {$ENDIF}
      {$IFDEF POSIX} [C_2018_ODBC, C_2017_ODBC, C_2016_ODBC, C_2012_ODBC, C_FreeTDS], C_FreeTDSLib {$ENDIF}
    );
Der 2012-NC kommt also erst nach dem 2017-ODBC.

Wie stellst du denn aktuell sicher, dass die Anwendung den Native Client verwendet?

haentschman 24. Mai 2024 06:10

AW: FireDAC Acync Fehler in der "Oberfläche" ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Wie stellst du denn aktuell sicher, dass die Anwendung den Native Client verwendet?
...auf den Clienten gibt es NUR den "NativeClient"...kein ODBC. (die wenigsten Probleme) In meiner Entwicklungsumgebung gibt es die 2 ODBC wegen dem MSSQL Server lokal.

Ich habe den ODBC 2017 entfernt. Jetzt nimmt meine Entwicklung auch den NativeClient. :wink: (Bild)

...der Fehler ist aber der gleiche. :cry:

Uwe Raabe 24. Mai 2024 10:11

AW: FireDAC Acync Fehler in der "Oberfläche" ?
 
Nur das ich das richtig verstehe: Der Fehler tritt auf, wenn du den Rechnungsempfänger wechselst und dann zu schnell den Tab anwählst?

In den Fall wäre es interessant zu wissen, was alles beim Tab-Wechsel passiert.

Zitat:

Zitat von haentschman (Beitrag 1537081)
Ich habe den ODBC 2017 entfernt. Jetzt nimmt meine Entwicklung auch den NativeClient.

Alternativ kannst du auch eine TFDPhysMSSQLDriverLink Komponente auf ein früh erzeugtes Form oder Datenmodul packen und dort den gewünschten Treiber einstellen.

In manchen Fällen ist die Entfernung eines neueren Treibers vielleicht keine Option.

haentschman 24. Mai 2024 11:29

AW: FireDAC Acync Fehler in der "Oberfläche" ?
 
Zitat:

Der Fehler tritt auf, wenn du den Rechnungsempfänger wechselst und dann zu schnell den Tab anwählst?
...ja.
Zitat:

In den Fall wäre es interessant zu wissen, was alles beim Tab-Wechsel passiert.
...eigentlich uninterressante Sachen. :wink:
Delphi-Quellcode:
procedure TfoReceipt.dxLayoutGroup1TabChanging(Sender: TObject; ANewTabIndex: Integer; var Allow: Boolean); // Wechsel Tab ->(2)
begin
  if (Datamodule.Kopf.State = dsEdit) or (Datamodule.Kopf.State = dsInsert) then
  begin
    Datamodule.Kopf.Post;
  end;
  if (Datamodule.Pos.State = dsEdit) or (Datamodule.Pos.State = dsInsert) then
  begin
    Datamodule.Pos.Post;
  end;
  StyleEditReceiptNumber(False);
end;
..
procedure TfoReceipt.StyleEditReceiptNumber(State: Boolean);
begin
  if State then
  begin
    cxDBTextEdit49.StyleReadOnly.Color := $00CD5151;
  end
  else
  begin
    cxDBTextEdit49.StyleReadOnly.Color := clBtnFace;
  end;
end;
Die einzige Verbindung der Datenmenge der Vorgabeartikel, ist die Verbindung über das Repository der Spalte "Artikelnummer" der Datenmenge Datamodule.Pos in der Ansicht Positionen (2)

:wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz