AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken [FireDAC][DatS]-1.Name[View] ist in der Liste doppelt vorhanden
Thema durchsuchen
Ansicht
Themen-Optionen

[FireDAC][DatS]-1.Name[View] ist in der Liste doppelt vorhanden

Ein Thema von Ykcim · begonnen am 13. Dez 2023 · letzter Beitrag vom 14. Dez 2023
Antwort Antwort
Ykcim

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

[FireDAC][DatS]-1.Name[View] ist in der Liste doppelt vorhanden

  Alt 13. Dez 2023, 16:56
Datenbank: MySQL • Version: 5 • Zugriff über: FireDac
Hallo Zusammen,
ich entwickle meine erste MultiThread Client-Server App und kämpfe mit Fehlermeldungen, die ich leider nicht einsortieren kann und zu denen ich auch keine weiterführende Hilfe / Posts gefunden habe...

Es werden von 10 Maschinen der aktuelle Status aus einer Datenbank abgefragt. Für jede Abfrage wird in der ClientApp ein eigener Thread der die Daten seiner Maschine vom Server abfragt.aufgemacht. Das funktioniert fehlerfrei wenn ich die serverseitige Datenbankabfrage weglasse.

Wenn ich clientseitig eine einzelne Maschine abfrage, funktioniert es auch ohne Probleme, nur wenn ich alle 10 Maschinen gleichzeitig abfrage, kommt es zu der Fehlermeldung:
Zitat:
Erste Gelegenheit für Exception bei $7518F932. Exception-Klasse EFDException mit Meldung '[FireDAC][DatS]-1. Name [View] ist in der Liste doppelt vorhanden'. Prozess SrvrApp.exe (16920)
Die Datenbankverbindung habe ich via eines TFDManager hergestellt. Den habe ich auf persistent gestellt und den CursorKind auf "ckStatic".
Die aufrufende Procedure erstellt vorab ein Object vom Typ TMxSQL, sodass es dort zu keiner Kollision kommen kann.

Der Fehler scheint beim Öffnen der Query in dieser Funktion zu entstehen:
Delphi-Quellcode:
procedure TMxSQL.Get_Settings(var Cols: TCols; var Rows: TRows; Tabelle: string; AStream: TStream);
var Logic: TLogic;
      qry_Settings: TFDQuery;
begin
   Logic:= TLogic.Create;
   Logic.Set_Query_FDMngr(qry_Settings, 'BDHMySQL');
   Try
      qry_Settings.sql.Add('select * from ' + Tabelle);
      ExecQuery(qry_Settings, Cols, Rows); //Hier wird die Query geöffnet und das Ergebnis in Arrays of string gespeichert
      if Assigned(AStream) then begin
         qry_Settings.SaveToStream(AStream, sfJSON);
      end;
   Finally
      Logic.Free;
   End;
end;
Aber ich vermute, dass es sich um ein generelles Problem handelt und nichts wirklich mit dieser Funktion zu tun hat.

Nachstehend mal der gesamte Weg:

ClientAPP:
Delphi-Quellcode:
procedure TFrm_Main_BSC.AdvGlowButton2Click(Sender: TObject); //Hier werden alle Maschine Staties abgefragt
begin
   Actually_MLifeData(Pnl_Top_CL1, true); //Wenn nur eine abgefragt wird, gibt es keine Probleme
   Actually_MLifeData(Pnl_Top_CL2, true);
   Actually_MLifeData(Pnl_Top_CL3, true);
   Actually_MLifeData(Pnl_Top_CL4, true);
   Actually_MLifeData(Pnl_Top_CL5, true);
   Actually_MLifeData(Pnl_Bottom_CL1, true);
   Actually_MLifeData(Pnl_Bottom_CL2, true);
   Actually_MLifeData(Pnl_Bottom_CL3, true);
   Actually_MLifeData(Pnl_Bottom_CL4, true);
   Actually_MLifeData(Pnl_Bottom_CL5, true);
end;
Actually_MLifeData
Delphi-Quellcode:
procedure TFrm_Main_BSC.Actually_MLifeData(BPanel: TPanel; RefreshData: boolean = false);
var CB:TDBAdvMultiColumnDropDown;
      MThread: TMyThreads;
begin
   MThread:= TMyThreads.Create;
   TThread.NameThreadForDebugging(BPanel.Name);
   Try
      CB := TDBAdvMultiColumnDropDown(FindComponent('MCDrbBx_'+BPanel.Name));
      if CB.Items.Items[CB.ItemIndex].Text[1] = 'then
         Exit;

      MThread.TH_Actually_FactoryScreen_Start(True);
      MThread.TH_Actually_FactoryScreen.Panel := BPanel;
      MThread.TH_Actually_FactoryScreen.Refresh := RefreshData;
      MThread.TH_Actually_FactoryScreen.MaschinenId := CB.Items.Items[CB.ItemIndex].Text[1];
      MThread.TH_Actually_FactoryScreen.Write_FactoryPanel := Write_MLifeData2;
      MThread.TH_Actually_FactoryScreen.Resume;
   Finally
      BPanel.Refresh;
      MThread.Free;
   End;
end;
Thread-Definition
Delphi-Quellcode:
{ TMyThread_Actually_FactoryScreen }

procedure TMyThread_Actually_FactoryScreen.Execute;
var MxSQL: TMxSQL;
      Logic: TLogic;
begin
   inherited;
   MxSQL:= TMxSQL.Create;
   Logic:= TLogic.Create;
   Try
      MxSQL.Get_MLifeData(fCols_MLifeData, fRows_MLifeData, fMaschinenId, fPanel.Name, fRefresh); //Hier werden die Daten von der ServerApp abgefragt
      Synchronize(procedure
                  begin
                     if Assigned(fWrite_FactoryPanel) then begin
                        fWrite_FactoryPanel(fPanel, fMaschinenId, fCols_MLifeData, fRows_MLifeData);
                     end;
                  end);
   Finally
      MxSQL.Free;
      Logic.Free;
   End;
end;
Anfrage der Daten von der ServerAPP
Delphi-Quellcode:
function TMxSQL.Get_MLifeData(var Cols: TCols; var Rows: TRows; Maschinen_ID, BPanel: string; RefreshData: boolean = false): TStream;
var LClient: TxDataClient;
      LService: IMyReportsService;
      LSTream: TMemoryStream;
      RStream: TMemoryStream;
      MTable: TFDMemTable;
      Logic: TLogic;
      StreamString: WideString;
      Methode: string;
      Cols_Set_Main: TCols;
      Rows_Set_Main: TRows;
begin
   MTable:= TFDMemTable.Create(nil);
   LClient := TXDataClient.Create;
   LStream := TMemoryStream.Create;
   RStream := TMemorySTream.Create;
   Logic := TLogic.Create;
   Try
      GetSettings('hlp_properties', Cols_Set_Main, Rows_Set_Main);
      ReadSettings('LifeMonitor_Methode',Cols_Set_Main, Rows_Set_Main);
      LClient.Uri:= DB_Unit.xData_Connect.URL;
      LService:= LClient.Service<IMyReportsService>;
      Methode := ReadSettings('LifeMonitor_Methode', Cols_Set_Main, Rows_Set_Main);
      if Methode = 'JSONthen begin
       // Weg über die vorhandene API-hier nicht relevant
      end
      else if Methode = 'QUERYthen begin
         LStream:=LService.Get_LifeMData(Maschinen_ID, RefreshData) as TMemoryStream;
         LStream.Position:= 0;
         MTable.Close;
         MTable.FieldDefs.Clear;
         MTable.Fields.clear;
         MTable.LoadFromStream(LStream, sfJSON);
         Logic.MTable_ColsRows(MTable, Cols, Rows);
      end
      else begin
         ShowMessage('Methode unbekannt');
         Exit;
      end;
      Result:= RStream;
   Finally
      Logic.Free;
      LClient.Free;
      LStream.Free;
      MTable.Free;
   end;
end;
Client Write Procedure ist in der Form definiert und schreibt die Daten in die entsprechende Felder.

Server AP
Delphi-Quellcode:
function TMyReportsService.Get_LifeMData(Maschinen_ID: string; RefreshData: boolean = false; SendData: boolean = true): TStream;
var MxSQL: TMxSQL;
      LStream: TMemoryStream;
begin
   MxSQL := TMxSQL.Create;
   LStream := TMemoryStream.Create;
   Try
      MxSQL.Get_act_MachineData(Maschinen_ID, LStream, RefreshData, SendData);
      Result := LStream;
   Finally
      MxSQL.Free;
   End;
end;
Abfrage der Daten
Delphi-Quellcode:
procedure TMxSQL.Get_act_MachineData(Machine_ID: string; LStream: TMemoryStream; RefreshData, SendData: boolean);
var Logic: TLogic;
      MsQuery: TFDQuery;
      CDMQuery: TFDQuery;
      DataTable: TFDMemTable;
      Operationslist: string;
      Cols_MData, Cols_OData: TCols;
      Rows_MData, Rows_OData: TRows;
      Cols_Set: TCols;
      Rows_Set: TRows;
begin
   if (RefreshData = false) and (DB_Modul.Tmr_LM_RefreshData.Enabled = false) and (SendData = true) then begin
      RefreshData := true;
      DB_Modul.Tmr_LM_RefreshData.Enabled := true;
      DB_Modul.FLM_OfflineState := 0;
      DB_Modul.Write_LM_Protokoll('RefreshTimer aktiviert.');
   end;

   if (RefreshData = false) and (DB_Modul.Tmr_LM_RefreshData.Enabled = true) and (SendData = true) then begin
      DB_Modul.Tmr_LM_RefreshData.Enabled := true;
      DB_Modul.FLM_OfflineState := 0;
      DB_Modul.Write_LM_Protokoll('OfflineState-Counter zurückgesetzt.');
   end;
   if (DB_Modul.Tmr_LM_RefreshData.Enabled = false) then begin
      DB_Modul.Tmr_LM_RefreshData.Enabled := true;
      DB_Modul.FLM_OfflineState := 0;
      DB_Modul.Write_LM_Protokoll('RefreshTimer aktiviert. OfflineState-Counter zurückgesetzt.');
   end;

   Logic := TLogic.create;
   try
      Logic.Set_Query_FDMngr(MsQuery, 'BDHAPS');
      Logic.Set_Query_FDMngr(CDMQuery, 'BDHCDM');
      if (RefreshData = true) then begin
         DB_Modul.Write_LM_Protokoll('RefreshProzess (' + Machine_ID + ') aktiviert.');
         Get_Settings(Cols_Set, Rows_Set, 'hlp_properties'); //In dieser Funktion scheint der Fehler zu entstehen
         DB_Modul.Write_LM_Protokoll('GetSettings (' + Machine_ID + ')');
         OperationsList := Read_Settings('Life_Data_OperationList', Cols_Set, Rows_Set);
         DB_Modul.Write_LM_Protokoll('ReadSettings (' + Machine_ID + ')');
         MsQuery.SQL.Add('SELECT TOP 1 '+
                                'CASE WHEN ( '+
                                  'concat(rj.JOB_ID, ' + QuotedStr(' ') + ', JOB_NAME) is NULL) then '+
                                  'LAG(Concat(rj.JOB_ID, ' + QuotedStr(' ') + ', rj.JOB_NAME)) OVER (ORDER BY re.TIME_LOCAL DESC) ELSE '+
                                  'concat(rj.JOB_ID, ' + QuotedStr(' ') + ',rj.JOB_NAME) end AS JOB_NAME, '+
                                'CONVERT( varchar( 10 ), re.Time_Local, 104 ) AS Datum, '+
                                'convert(char(5), re.Time_Local, 108) AS Startzeit, '+
                                'rd.device_id, '+
                                'rd.device_name, '+
                                'ro.OPERATION_NAME, '+
                                'ry.FAMILY_NAME AS Operator, '+
                                'CASE WHEN ( '+
                                  'DateDiff(minute, re.Time_Local, LAG(re.Time_Local) OVER (ORDER BY re.TIME_LOCAL DESC)) is NULL) then '+
                                  'Concat(DateDiff(minute, re.Time_Local, GETDATE()),' + QuotedStr(':00 (') + ',convert(char(5), re.Time_Local, 108), ' + QuotedStr(')') + ') ELSE '+
                                  'ConCat(DateDiff(minute, re.Time_Local, LAG(re.Time_Local) OVER (ORDER BY re.TIME_LOCAL DESC)),' + QuotedStr(':00 (') + ',convert(char(5), re.Time_Local, 108), ' + QuotedStr(')') + ') end AS Dauer, '+
                                '(SELECT SPEED FROM RBC_DEVICE_BASIC_INTERVALS RDB WHERE RDB.DEVICE_BASIC_INTERVAL_KEY = '+
                                  '(SELECT MAX(Device_Basic_interval_key) FROM RBC_DEVICE_BASIC_INTERVALS RDBI WHERE RDBI.DEVICE_KEY = re.DEVICE_KEY)) AS Speed, '+
                                'CASE WHEN (max(ws.GOOD_CYCLES) = 0 OR max(ws.planned_good_cycles)=0) THEN 0 ELSE '+
                                    'ROUND(max(ws.GOOD_CYCLES)/max(ws.planned_good_cycles),2)*100 END as PERCENT_COMPLETED, '+
                                'ws.PLANNED_GOOD_AMOUNT, '+
                                'ws.GOOD_CYCLES, '+
                                'ro.OPERATION_KEY, '+
                                'ws.WORK_STEP_NAME, '+
                                'sj.CUSTOMER_NAME '+
                         'from RPS_EVENTS re '+
                         'LEFT JOIN RPS_WORK_STEPS ws ON ws.WORK_STEP_KEY = re.WORK_STEP_KEY '+
                         'LEFT JOIN RPS_JOBS rj ON rj.JOB_KEY = ws.JOB_KEY '+
                         'LEFT JOIN RPS_EMPLOYEE_ACTIVITIES ea ON ea.WORK_STEP_KEY = ws.WORK_STEP_KEY '+
                         'LEFT JOIN RPS_OPERATIONS ro ON ro.OPERATION_KEY = re.OPERATION_KEY '+
                         'LEFT JOIN RBC_DEVICES rd ON rd.device_key = re.device_key '+
                         'LEFT JOIN RBC_EMPLOYEES ry ON ry.EMPLOYEE_KEY = ea.EMPLOYEE_KEY '+
                         'LEFT JOIN SPS_JOB sj ON sj.JOBID = rj.JOB_ID '+
                         'WHERE rd.DEVICE_ID = :Device_ID '+
                         'AND CONVERT( date, re.TIME_LOCAL) = CONVERT( date, GETDATE()) '+
                         'AND ( re.OPERATION_KEY IN ( ' + OperationsList + ' ) OR (re.OPERATION_KEY IS NULL) AND (rd.DEVICE_ID = ' + QuotedStr('Suprasetter@BDHSHOOTER') + ')) '+
                         'GROUP BY rj.JOB_NAME, '+
                                  'rj.job_id, '+
                                  're.Time_Local, '+
                                  're.Device_key, '+
                                  'rd.device_id, '+
                                  'rd.device_name, '+
                                  're.OPERATION_KEY, '+
                                  'ro.OPERATION_KEY, '+
                                  'ro.OPERATION_NAME, '+
                                  'ry.FIRST_NAME, '+
                                  'ry.FAMILY_NAME, '+
                                  'ws.PERCENT_COMPLETED, '+
                                  'ws.PLANNED_GOOD_AMOUNT, '+
                                  'ws.GOOD_CYCLES, '+
                                  'ws.WORK_STEP_NAME, '+
                                  'sj.CUSTOMER_NAME '+
                         'ORDER BY re.TIME_LOCAL desc ');
         MsQuery.ParamByName('Device_ID').AsString := Machine_ID;
         MsQuery.Open;
         //Daten in Datentabelle kopieren und für Clientabfragen verfügbar machen
         DataTable := TFDMemtable(DB_Modul.FindComponent('FDTbl_LM_' + StringReplace(Machine_ID, '@','_',[rfIgnoreCase, rfReplaceAll])));
         DataTable.CopyDataSet(MsQuery, [coStructure, coRestart, coAppend]);
         DB_Modul.Write_LM_Protokoll('Refresh DatenTabelle Maschine ' + Machine_ID);
         DB_Modul.Write_LM_Protokoll('RefreshProzess (' + Machine_ID + ') beendet.')
      end;

      if SendData then begin
         if Assigned(LStream) then begin
            DataTable := TFDMemtable(DB_Modul.FindComponent('FDTbl_LM_' + StringReplace(Machine_ID, '@','_',[rfIgnoreCase, rfReplaceAll])));
            if DataTable.State = dsInactive then begin
               DB_Modul.Write_LM_Protokoll('FDTable('+Machine_ID+') ist inaktiv. Wartezeit 2 Sek.');
               Sleep(2000);
            end;
            if DataTable.State = dsBrowse then begin
               DataTable.SaveToStream(LStream, sfJSON);
               DB_Modul.Write_LM_Protokoll('Sent Daten ('+Machine_ID+') LifeMonitor.');
            end
            else begin
               DB_Modul.Write_LM_Protokoll('ERROR: FDTable nicht aktiv ('+Machine_ID+').');
            end;
         end
         else begin
            DB_Modul.Write_LM_Protokoll('ERROR: No Stream assigned ('+Machine_ID+').');
         end;
      end;
   Finally
      CDMQuery.Free;
      MsQuery.Free;
      Logic.Free;
   end;
end;;
Der Fehler scheint beim Öffnen der Query in dieser Funktion zu entstehen:
Delphi-Quellcode:
procedure TMxSQL.Get_Settings(var Cols: TCols; var Rows: TRows; Tabelle: string; AStream: TStream);
var Logic: TLogic;
      qry_Settings: TFDQuery;
begin
   Logic:= TLogic.Create;
   Logic.Set_Query_FDMngr(qry_Settings, 'BDHMySQL');
   Try
      qry_Settings.sql.Add('select * from ' + Tabelle);
      ExecQuery(qry_Settings, Cols, Rows); //Hier wird die Query geöffnet und das Ergebnis in Arrays of string gespeichert
      if Assigned(AStream) then begin
         qry_Settings.SaveToStream(AStream, sfJSON);
      end;
   Finally
      Logic.Free;
   End;
end;
ExecQuery
Delphi-Quellcode:
function TMxSQL.ExecQuery (query: TFDQuery; var Cols: TCols; var Rows: TRows; AddRows: integer = 0): integer;
var I, J: integer;
begin
   Query.Open; //Hier kracht es
   SetLength(Cols,0);
   SetLength(Rows,0, 0);
   SetLength(Cols,Query.FieldCount);
   SetLength(Rows,Query.FieldCount, Query.RecordCount+AddRows); //+1 für FloatFooter
   for J:=0 to Query.FieldCount -1 do begin
      Cols[J]:=Query.Fields.Fields[J].FieldName;
   end;
   for I:=0 to Query.RecordCount -1 do begin
      for J:=0 to Query.FieldCount -1 do begin
         Rows[J,I]:=Query.Fields.Fields[J].AsString;
      end;
      query.Next;
   end;
   Result := Query.RecordCount;
end;

Aber ich vermute, dass es sich um ein generelles Problem handelt und nichts wirklich mit dieser Funktion zu tun hat.

Ich wäre für Eure Unterstützung wirklich sehr dankbar. Habe keine Idee mehr, wie ich mich dem Problem noch nähern soll.

Vielen Dank
Patrick
Patrick

Geändert von Ykcim (13. Dez 2023 um 17:04 Uhr)
  Mit Zitat antworten Zitat
Ykcim

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

AW: [FireDAC][DatS]-1.Name[View] ist in der Liste doppelt vorhanden

  Alt 13. Dez 2023, 18:52
Hallo Zusammen,

das ist kein PUSH!

Ich habe von dem TFDManager die Einstellung ResourceOptions/MaxCursors von -1 auf 50 geändert. Ich dachte -1 stände für unbegrenzt...
Dann ist die Anwendung 15 Minuten mit einer Abfrage alle 20 Sekunden ohne Fehler durchgelaufen.
Ich habe zwar im TaskManager beobachtet, dass ich einen Speicher irgendwo nicht freigegeben habe, denn der Speicher ist bei jeder Abfrage von der ServerApp um ca. 3MB gestiegen.

Nach 15 Minuten kam dann leider doch wieder eine Fehler bei der gleichen Funktion mit dem Hinweis "Vorherige Aktion noch nicht abgeschlossen".

Das ist schon zumindest ein Schritt in die richtige Richtung, den ich Euch mitteilen wollte.

LG Patrick
Patrick
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.490 Beiträge
 
Delphi 7 Professional
 
#3

AW: [FireDAC][DatS]-1.Name[View] ist in der Liste doppelt vorhanden

  Alt 13. Dez 2023, 19:32
Du öffnest im Ablauf mehrere Querys. Im Quelltext kann ich aber keine entsprechende Anzahl von Close finden.
Vor der Freigabe der Querys würd' ich explizit ein Close aufrufen.
Delphi-Quellcode:
procedure TMxSQL.Get_Settings(var Cols: TCols; var Rows: TRows; Tabelle: string; AStream: TStream);
var Logic: TLogic;
      qry_Settings: TFDQuery;
begin
   Logic:= TLogic.Create;
   Logic.Set_Query_FDMngr(qry_Settings, 'BDHMySQL');
   Try
      qry_Settings.sql.Add('select * from ' + Tabelle);
      ExecQuery(qry_Settings, Cols, Rows); //Hier wird die Query geöffnet und das Ergebnis in Arrays of string gespeichert
      if Assigned(AStream) then begin
         qry_Settings.SaveToStream(AStream, sfJSON);
      end;
      qry_Settings.Close; // Wird nicht mehr benötigt, daher zumachen.
   Finally
      qry_Settings.Free; // Freigabe der Query, oder erfolgt die Freigabe
                         // automatisch in Logic.Free?
      Logic.Free;
   End;
end;
Wenn AStream zwingend erforderlich ist, kann man sich bei if not Assigned(AStream) die Routine sparen, daher würd' ich die Prüfung an den Anfang verschieben.
Delphi-Quellcode:
procedure TMxSQL.Get_Settings(var Cols: TCols; var Rows: TRows; Tabelle: string; AStream: TStream);
var Logic: TLogic;
      qry_Settings: TFDQuery;
begin
   if not Assigned(AStream) then exit; // und passende Fehlermeldung ins Protokoll, sonst sucht man sich ggfls. 'nen Wolf nach 'nem vollkommen anderen Fehler im SQL, der zwar nicht existiert, aber durch den fehlenden Stream "übertünscht" wird.

   Logic:= TLogic.Create;
   Logic.Set_Query_FDMngr(qry_Settings, 'BDHMySQL');
   Try
      qry_Settings.sql.Add('select * from ' + Tabelle);
      ExecQuery(qry_Settings, Cols, Rows); // Hier wird die Query geöffnet und das Ergebnis in Arrays of string gespeichert
      qry_Settings.SaveToStream(AStream, sfJSON);
      qry_Settings.Close; // Wird nicht mehr benötigt, daher zumachen.
   Finally
      qry_Settings.Free; // Freigabe der Query, oder erfolgt die Freigabe
                         // automatisch in Logic.Free?
      Logic.Free;
   End;
end;
Und ehrlich gesagt hab' ich keine Ahnung, ob es das geschielderte Ursprungsproblem löst, aber in Bezug auf
Zitat von Ykcim:
Ich habe zwar im TaskManager beobachtet, dass ich einen Speicher irgendwo nicht freigegeben habe, denn der Speicher ist bei jeder Abfrage von der ServerApp um ca. 3MB gestiegen.
bin ich optimistisch.
  Mit Zitat antworten Zitat
Ykcim

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

AW: [FireDAC][DatS]-1.Name[View] ist in der Liste doppelt vorhanden

  Alt 14. Dez 2023, 15:55
Hallo Zusammen,
ich glaube, es ist gelöst. Ich habe den Querys, die erstellt wurden, immer eine Connection gegeben, die auf die ConnectionDefs des Managers verweisen und nachdem sie nicht mehr benötigt werden, wie freigegeben werden.

Ich habe mich dabei an diesem Artikel orientiert:
https://docwiki.embarcadero.com/RADS...ding_(FireDAC)

Das sieht dann exemplarisch so aus:
Delphi-Quellcode:
procedure TMxSQL.Get_Settings(var Cols: TCols; var Rows: TRows; Tabelle: string; AStream: TStream);
var Logic: TLogic;
      qry_Settings: TFDQuery;
      oConn_MySQL: TFDConnection;
begin
   Logic:= TLogic.Create;
   Logic.Set_Query_FDMngr2(qry_Settings, oConn_MySQL, 'BDHMySQL');
   Try
      qry_Settings.sql.Add('select * from ' + Tabelle);
      ExecQuery(qry_Settings, Cols, Rows);
      if Assigned(AStream) then begin
         qry_Settings.SaveToStream(AStream, sfJSON);
      end;
      qry_Settings.Close;
      oConn_MySQL.Close;
   Finally
      qry_Settings.Free;
      oConn_MySQL.Free;
      Logic.Free;
   End;
end;
Delphi-Quellcode:
procedure TLogic.Set_Query_FDMngr2(var Query: TFDQuery; var oConn: TFDConnection; Database: string);
begin
   oConn := TFDConnection.Create(nil);
   oConn.ConnectionDefName := Database;
   Query:= TFDQuery.Create(nil);
   query.Connection:= oConn;
   Query.SQL.Clear;
   Query.FetchOptions.AutoFetchAll;
   Query.FetchOptions.Mode := fmAll;
end;
Damit ist die Anwendung heute ca. 40 Minuten ohne Fehler gelaufen... Ich hoffe, dass war wirklich die Lösung
Ich habe mir die Verbindungen auf der Datenbank angesehen, dass waren ca. 11 die aber konstant blieben...

@Delphi.Narium
Du hattest Recht, ich hatte
qry_Settings.Free; vergessen. Jetzt läuft der Speicher bei der App nicht mehr voll.

Zitat:
Wenn AStream zwingend erforderlich ist, kann man sich bei if not Assigned(AStream) die Routine sparen, daher würd' ich die Prüfung an den Anfang verschieben.
Das soll so sein, denn der Stream kann auch nil sein, wenn die Daten nicht an den Client gesendet werden, sondern nur in der ServerApp verwendet werden.

Vielen Dank, ich bastel mal weiter und hoffe, keine bösen Überraschungen zu erleben.

LG Patrick
Patrick
  Mit Zitat antworten Zitat
Antwort Antwort


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:01 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