AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Werte aus Liste in Datenbank schreiben, Netzunterbrechung abfangen

Werte aus Liste in Datenbank schreiben, Netzunterbrechung abfangen

Ein Thema von norwegen60 · begonnen am 16. Sep 2017 · letzter Beitrag vom 16. Sep 2017
Antwort Antwort
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
504 Beiträge
 
Delphi 12 Athens
 
#1

Werte aus Liste in Datenbank schreiben, Netzunterbrechung abfangen

  Alt 16. Sep 2017, 09:34
Datenbank: MsSQL • Version: 2008 • Zugriff über: UniDac
Hallo zusammen,

ich möchte in einem Thread eine TObjectlist in eine MsSQL-Datenbank schreiben.

Folgende Voraussetzungen sind vorhanden:
  • Die Liste wird während eines Messzyklus mit 10 Werten/Sekunde ergänzt
  • Die Liste ist eine Threadsave Kopie der eigentlichen Messliste
  • In der Liste sind immer nur die Werte, die noch nicht in DB gesichert wurden
  • Im Normalfall reicht Zeit aus um Daten immer gleich in DB zu schreiben

Jetzt soll aber zusätzlich sichergestellt werden, dass Daten auch dann weggeschrieben werden, wenn die Datenbankverbindung Unterbrechungen aufweist. Natürlich erst dann, wenn Verbindung wieder da.

Hier mein bisheriger Code.
Delphi-Quellcode:
procedure TThrSaveCalForce.Execute;
var
  lstCopy, lstTmp: TList;
  i, iLast: Integer;
  Values: TCalForce;

begin
  inherited;

  FStatus := FormatDateTime('ss.zzz', now) + ' Execute Start';
  Synchronize(syncStatusEvent);
  CoInitialize(nil);

  iLast := 0;
  lstCopy := TList.Create;
  dbQuery.Close;

  try
    while not (Terminated) do
    begin

      // Noch nicht bearbeitete Daten in Temporäre Liste kopieren
      try
        System.TMonitor.Enter(lstCalForceProc);
        Values := TCalForce.Create;
        for i := iLast to lstCalForceProc.Count - 1 do
        begin
          Values := lstCalForceProc.Items[i];
          lstCopy.Add(Values);
        end;
        iLast := i + 1;
      finally
        System.TMonitor.Exit(lstCalForceProc);
      end;

      if lstCopy.Count > 0 then
      begin
        // Kopierte Daten abhandeln (z.B. in DB speichern) und Liste wieder löschen
        try
          dbQuery.Open;

          if dbQuery.Active then
          begin
            while lstCopy.Count > 0 do
            begin
              Values := lstCopy.Items[0];

              if (Values.Art <> '') then
              begin
                dbQuery.Insert;
                dbQuery.FieldByName('CalReportID').Value := FReportID;
                dbQuery.FieldByName('Fact').Value := Values.Fact;
                dbQuery.FieldByName('FTarget').Value := Values.Ftarget;
                dbQuery.FieldByName('Art').Value := Values.Art;
                dbQuery.FieldByName('Temperatur').Value := Values.Temperatur;
                dbQuery.FieldByName('Humidity').Value := Values.Humidity;
                dbQuery.FieldByName('ServOrt').Value := FServOrt;
                dbQuery.FieldByName('ErstUserID').Value := FUserID;
                dbQuery.FieldByName('ErstDat').Value := Values.ErstDat;
                dbQuery.Post;
                FStatus := format('RepID = %d, Force = %6.2fN, Temp = %5.2f°C', [FReportID, Values.Fact, Values.Temperatur]);
                Synchronize(syncStatusEvent);
                OutputDebugString(pChar(FStatus));
              end;
              lstCopy.Delete(0); // gepeicherten Satz in lstCopy löschen
            end;
          end;
        finally
          dbQuery.Close;
        end;
      end;
      Sleep(100);
    end;
  finally
    lstCopy.Free;
  end;
  IsRunning := false;
end;
Meine Fragen:
  • Wie stelle ich schnellstmöglich fest, ob eine Verbindung besteht?
  • Bietet ein Insert direkt per "INSERT INTO TabName VALUES (FReportID, Values.Fact, ...)" Vorteile?
  • Wenn ja, bietet es Vorteile wenn ich alle Werte der Liste in ein Insert packe (Values (ListenWerte1), (ListenWerte2) ...). Unter Beachtung der maximal zulässigen Anzahl (1000)?
  • Muss nach einem Unterbruch die Connection manuell geöffnet werden oder öfnnet die sich automatisch mit dem dbQuery.Open?

Ich könnte das jetzt ausprobieren, aber meine Erfahrung ist, dass manches beim Probieren funktioniert, aber trotzdem nicht sauber ist und irgendwann schief geht. Deshalb wäre ich für Ratschläge dankbar

Grüße
Gerd
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#2

AW: Werte aus Liste in Datenbank schreiben, Netzunterbrechung abfangen

  Alt 16. Sep 2017, 13:36
Es spricht nichts gegen ein Insert Statement, im Gegenteil, besonders nicht in einer geschützen Umgebung (Injektion).
Ggf. kann man (sehr) viele Statements in eine Datei packen und als Script einfügen.
Das ginge auch sehr problemlos bei Offline:
Dateien auf den Server übertragen (wann immer es geht)
Dateien per Script in die DB laden, wenn immer welche da sind.
Das kann man ggf so gestalten, dass mehrere Insert prozesse arbeiten (können), wenn mal Stau war. Aber je nach Lockfähigkeit der DB (hier gleich Version von mssql) ist das vielleicht auch problematisch mit Parallelbetrieb.

Mehre Statements in einem Query funktionieren mit den meisten Komponenten dagegen nicht.
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.169 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Werte aus Liste in Datenbank schreiben, Netzunterbrechung abfangen

  Alt 16. Sep 2017, 14:27
Du kannst deine Lösung stark beschleunigen wenn du mehre Inserts gleichzeitig abschickst.

INSERT INTO Tab1(Feld1, Feld2, Feld3)
VALUES('A1', 'B1', 'C1'), ('A1', 'B2', 'C2'), (...), (...)...

Das dann alles noch schick mit Parameter und Prepared Statements "geschmückt" und deine Anwendung ist um einiges schneller als wenn du die Datensätze versuchst einzeln in die DB zu bringen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
504 Beiträge
 
Delphi 12 Athens
 
#4

AW: Werte aus Liste in Datenbank schreiben, Netzunterbrechung abfangen

  Alt 16. Sep 2017, 20:43
INSERT INTO Tab1(Feld1, Feld2, Feld3)
VALUES('A1', 'B1', 'C1'), ('A1', 'B2', 'C2'), (...), (...)..
Das war, was ich mit
Zitat:
wenn ich alle Werte der Liste in ein Insert packe (Values (ListenWerte1), (ListenWerte2) ...).
gemeint habe. Ich muss aber dazu sagen, dass im Normalfall jeder Datensatz gesendet werden kann bevor der nächste anfällt. D.h. bei stabiler Verbindung enthält die Liste meist nur einen Satz.

Mein Hauptproblem aber ist:
Wie stelle ich fest ob die Daten erfolgreich geschrieben wurden (und ich sie in der Lise löschen kann) oder ob die Datenbankverbindung unterbrochen ist und ich den Insert wiederholen muss? Ist da der Try ... Except der richtige Weg?
  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 06:24 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