Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   onUpdateRecord für Progressbar nutzen (https://www.delphipraxis.net/207941-onupdaterecord-fuer-progressbar-nutzen.html)

Marco Steinebach 18. Mai 2021 21:24

Datenbank: Firebird • Version: 3.0 • Zugriff über: IBDAC

onUpdateRecord für Progressbar nutzen
 
Hallo zusammen,
Ich habe hier eine Menge Inserts, und möchte, da das Ganze recht lange läuft, eine Progressbar anzeigen.
CachedUpdates stehen auf true, und wenn ich
a.ApplyUpdates;
ausführe, ist, erstmal, Ruhe im Schiff. ;-)
Nun bin ich über das Event
OnUpdateRecord
gefallen, das, so habe ich es verstanden,bei jedem Update eines Records (sprich auch beim Insert) aufgerufen wird.
Das stimmt auch, aber er macht jetzt keine Update mehr, sprich, die Tabelle ist leer.
Ok, die "Automatik" ist, wenn man das Event nutzt, abgeschaltet, aber ich will doch nur zählen...

Code:
procedure TDatenbank.AbfrageUpdateRecord(DataSet: TDataSet;
  UpdateKind: TUpdateKind; var UpdateAction: TUpdateAction);
begin
  iNochDa := iNochDa - 1; // Zähler, der am Anfang die Zahl der noch einzufügenden Datensätze enthält.
  if (iNochDa > 0) and (iNochDa mod 50 = 0) then
    splashformular.status (format ('Noch %d %s zu importieren.', [iNochDa, iTabelle]));
  updateAction := uaApplied;
end;
Wo ist mein Fehler, sprich, wie kriege ich ihn dazu, die Updates, trotz meines Events, trotzdem zu machen?

Für Antworten wäre ich sehr dankbar.

Herzlich grüßt
Wandogau

himitsu 18. Mai 2021 22:31

AW: onUpdateRecord für Progressbar nutzen
 
Bekommt die GUI währenddessen auch Gelegenheit/Zeit sich zu zeichnen?
(k.A. was splashformular.status macht)

Dauern die INSERTs selber wirklich soooo lange (nur die Zeit in der DB), oder liegt es nur an der Masse an einzelnen DB-Anfragen?


Warum die Inserts nicht als ein Statement in die DB schieben?
Dann bleibt nur die Reine Arbeitszeit in der DB übrig,
anstatt der Masse an einzelnen Statements, inkl. der Zeit in der DB-Komponente.
SQL-Code:
INSERT INTO table_name
  (column1, column2, column3)
VALUES
  (value11, value12, value13),
  (value21, value22, value23),
  (value31, value32, value33),
  (value41, value42, value43),
  (value51, value52, value53),
  (value61, value62, value63);
Kann man mit einer passenden Escape-/QuoteFunktion zusammenbauen, aber ginge auch mit Parametern. (Statement zusammenbauen und dann die Parameter der Reihe nach füllen.)


Am Einfachstens ist es natürich ohne CachedUpdates, wo ohne Umstände vor/nach den Dataset.Insert/Post gezählt werden kann.

Und man kann natürlich auch die Dinge in einen Thread schieben, denn dann hat die GUI immer genug Zeit für sich.

Delphi.Narium 19. Mai 2021 09:55

AW: onUpdateRecord für Progressbar nutzen
 
Doku lesen: http://docwiki.embarcadero.com/Libra....TUpdateAction
Zitat:

Zitat von uaApplied
The event handler applied the update (not used in error handling event handlers). Free the current record update from the cache.

Zitat:

Zitat von DeepL - Übersetzung für uaApplied
Der Ereignishandler, der die Aktualisierung durchgeführt hat (wird nicht in Ereignishandlern zur Fehlerbehandlung verwendet). Gibt die aktuelle Datensatzaktualisierung aus dem Cache frei.

Grob gesagt: Du möchtest doch nur den Status ausgeben.
Warum gibtst Du dann nicht nur den Status aus?

Ist dashier
Delphi-Quellcode:
updateAction := uaApplied;
wirklich erforderlich? Für die Statusausgabe?

himitsu Vorschlag ist übrigens die deutlich bessere Alternative für Datenbankinserts. Vor allem, wenn es um viele Daten geht. Mag sein, dass die Implementierung erstmal ein bisserl aufwändiger ist, kann aber, bei größeren Datenmengen, schonmal die eine oder andere Stunde Laufzeit einsparen (und die Nutzung einer Progressbar zur Statusausgabe überflüssig machen).

Applied heißt übrigens sowas wie: angewandt, erledigt.

Sprich: mit
Delphi-Quellcode:
updateAction := uaApplied;
sagst Du der Routine, fertig, hab' ich gemacht, musst Du Dich nicht mehr drum kümmern. Und die Routine hält sich dran und kümmert sich nicht mehr drum und damit ist die Tabelle anschließend korrekterweise leer ;-)

Marco Steinebach 19. Mai 2021 17:34

AW: onUpdateRecord für Progressbar nutzen
 
Hallo ihr beiden,
das uaApplied genau das sagt, nämlich: isch hab mich drum gekümmert, hab ich mir schon gedacht, wenn man die UpdateAction gar nicht anpackt, passiert das selbe.
Aber egal, die CachedUpdates hab ich mir jetzt geschenkt.
Schade nur, dass mein FireBird keine Multiplen Inserts mag, aber meine Güte, das läuft nur einmal beim Versionwechsel zum Datenimport und dann nimmermehr, ;-), so dass hier die ein oder andere Sekunde, die sich einsparen ließe, vernachlässitgt werden kann.

Ganz herzlichen Dank für eure Antworten und herzliche Grüße
Wandogau

himitsu 19. Mai 2021 17:37

AW: onUpdateRecord für Progressbar nutzen
 
Ach, das Execute wird dann einfach nur ein bissl länger. :stupid:

SQL-Code:
INSERT INTO table_name (column1, column2, column3) VALUES (value11, value12, value13);
INSERT INTO table_name (column1, column2, column3) VALUES (value21, value22, value23);
INSERT INTO table_name (column1, column2, column3) VALUES (value31, value32, value33);
INSERT INTO table_name (column1, column2, column3) VALUES (value41, value42, value43);
INSERT INTO table_name (column1, column2, column3) VALUES (value51, value52, value53);
INSERT INTO table_name (column1, column2, column3) VALUES (value61, value62, value63);
oder
SQL-Code:
INSERT INTO table_name (column1, column2, column3)
        SELECT value11, value12, value13
  UNION SELECT value21, value22, value23
  UNION SELECT value31, value32, value33
  UNION SELECT value41, value42, value43
  UNION SELECT value51, value52, value53
  UNION SELECT value61, value62, value63);

-- für ein einfaches SQL-Zusammenbauen, einfach als erstes SELECT z.B. ein
        SELECT null, null, null WHERE false

Frickler 19. Mai 2021 18:15

AW: onUpdateRecord für Progressbar nutzen
 
Mach um je 100 Inserts einen EXECUTE BLOCK drumrum, dann gehts ein bisschen schneller.

Delphi.Narium 20. Mai 2021 10:26

AW: onUpdateRecord für Progressbar nutzen
 
Oder einfach einen Export (in der Form, wie himitsu ihn beschreibt) in eine Datei schreiben und die dann auf der Kommandozeile (oder per ShellExceute) mit isql in die Datenbank jagen. Dann macht das FireBird alles alleine. Und FirdBird kann das alleine schneller, als wir es über Delphi und die dann genutzte Datenbankschnittstelle je hinbekommen können.

Man braucht dann auch nicht für jede Tabelle eine passende Rotuine oder für jede Tabelle ein eigenes Script, sondern kann das alles problemlos in eine Datei packen.

Alle ca. 100 Sätze ein Commit dazwischen oder zwischen die Tabellen macht es eventuell schneller.

Macht man kein Commit dazwischen, sondern nur eins ans Ende (was man aber keinesfalls vergessen darf!!!), hat man den gesamten Import in einer Transaktion. Kracht es zwischendurch, hat man dann garantiert keinen inkonsitenten Datenbestand. Bei einer satzweisen Lösung per Delphi, würd' ich meine Hand dafür nicht ins Feuer legen ;-) (Derweil man muss sich dann selbst um den konsisteneten Ablauf der Transaktionen kümmern.)
Code:
isql -u Benutzername -p passwort -i x:\Pfad\DieDateiMitDenInsertStatements.sql x:\PPfad\Datenbankname.fdb


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