Einzelnen Beitrag anzeigen

norwegen60

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

Werte aus Liste in Datenbank schreiben, Netzunterbrechung abfangen

  Alt 16. Sep 2017, 10: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