[Gelöst] Re-Initialisierung temporärer Records

18. Februar 2008 10:58

Hallo Allerseits,

hab mal wieder eine Anfänger-Frage: Wie setze ich (z.B. innerhalb eines Loops) "gebrauchte" tmp. Record-Variablen wieder auf einen Null-Zustand zurück?

Wie wir ja schon anderweitig diskutiert haben, leert das CLEAR nur die Felder des aktuell im Zugriff befindlichen Datensatzes.

Bisher hab ich nun immer zuerst einen RESET gesetzt, dann ein DELETEALL, um die Variable wirklich zu leeren.

Am Wochenende hatte ich nun einen üblen Effekt: Es geht darum, im Loop mehrere datensätze abzuarbeiten. Für jeden Datensatz nun gilt es, einen *teilweise gefüllten* Record mit genau einer Datenzeile an eine Funktion zu übergeben. Aus der Fkt. kommt der Record dann vollständig gefüllt zurück und wird weiter verarbeitet. Zum nächsten Loop wird die Variable dann wie beschrieben mit RESET und DELETEALL wieder initialisiert.

Nun das Pikante: Beim Anlegen des Datensatzes bleibt ausgerechnet das Key-Feld zunächst leer.

Effekt: Beim ersten Loop läuft alles wie gewollt. Beim zweiten Loop allerdings bleiben "irgendwie" trotz RESET und DELETEALL die Werte des ersten Eintrags noch erhalten!

Lege ich den neuen DS ordentlich mit INIT, Zuweisung und INSERT an, und weise dabei auch das Key-Feld zu, dann läuft alles wie erwartet. Will ich aber das Key-Feld leer lassen (leeres Code-Feld), dann bleibt der Code aus dem ersten Loop drin!

Erst, wenn ich n ach dem RESET und DELETEALL auch noch ein CLEAR mache, dann läuft es richtig.

Also hab ich jetzt zwecks Re-Initalisierung im konkreten Fall 4 Record-Variablen, die ich alle initalisiere, indem für alle zuerst das RESET, dann das DELETEALL und dann das CLEAR ausführe.

Ich finde, das sieht irgendwie ziemlich krank aus und stört mein ästhetisches Empfinden ganz erheblich.

Die Frage: Wie löst man solch ein triviales Problem professionell?

Zur Verdeutlichung ein Beispiel:

Code:

tmprec_Taskliste.FIND('-')
REPEAT

  //Initialisierung der tmp. Records
  tmprec_Headerdata1.RESET;
  tmprec_Lines1         .RESET;
  tmprec_Headerdata2.RESET;

  tmprec_Headerdata1.DELETEALL;
  tmprec_Lines1         .DELETEALL;
  tmprec_Headerdata2.DELETEALL;

  CLEAR(tmprec_Headerdata1);
  CLEAR(tmprec_Lines1);
  CLEAR(tmprec_Headerdata2);

  tmprec_Headerdata1.INIT;
  tmprec_Headerdata1.Description := 'Blablabla';
  //tmprec_Headerdata1.Code bleibt leer, wird durch Funktion später gefüllt
  tmprec_Headerdata1.INSERT;

  tmprec_Headerdata2.INIT;
  tmprec_Headerdata2.Code := '1123';
  tmprec_Headerdata2.INSERT;

  //Fkt-Call; Übergabe der Recs mit VAR-Flag. Recs werden in der Fkt. vervollständigt
  FillAndValidateRecords(tmprec_Headerdata1,tmprec_Lines1,tmprec_Headerdata2);
 
  //Weiterverarbeitung der Recs
  //...

UNTIL tmprec_Taskliste=0;



Viele Grüße,

SF
Zuletzt geändert von SafetyFirst am 20. Februar 2008 14:07, insgesamt 1-mal geändert.

18. Februar 2008 21:27

Ich bräuchte hier noch inhaltliche Hilfe:
tmprec_Taskliste: Was wird da durchlaufen? Eine Standardtabelle, die offenbar gefüllt ist? (ganz unten sollte dann aber UNTIL tmprec_Taskliste.NEXT =0; stehen)

Was sind entsprechend tmprec_Headerdata1, tmprec_Headerdata2 und tmprec_Lines1?

Die Sourcetabellen sind deswegen wichtig, weil du offenbar in einer Schleife per INSERT temp. Records erzeugst, ohne jedoch den Primärschlüssel zu unterscheiden (kann auch an der Abstraktion liegen).

Zuletzt:
Wozu brauchst du hier temp. Records?
Auch nicht temporäre Records sind bis zu einem gewissen Maß geeignet, variable Inhalte an eine verarbeitende Funktion aufzurufen.

20. Februar 2008 10:46

Hallo Natalie,

das Problem ist, daß ich einen komplexen Satz Daten von Extern bekomme, die ich in unserer Tabellenstruktur ablegen muß, d.h. ich bekomme verschiedene, fachlich zusammengehörende Entitäten, teilweise mit mehreren Datensätzen, die aber "zusammangehören". Die Qualität der Daten, die hereinkommen, sei zunächst undefiniert, und ich muß die Daten validieren und ggf. vervollständigen.

Ich verwende einen Satz von tmp. Record-Variablen, die die zukünftige Struktur schon spiegeln, und prozessiere nun den Input. Erst wenn die Daten vollständig validiert sind, schreibe ich sie dann auch wirklich in die Tabellen. Detektiere ich Inkonsistenzen oder fehlende, wichtige Parameter, die nicht aus dem Prozess heraus generiert werden können, so sollen die Daten komplett abgewiesen werden.

Zu Deinen Fragen:
Ja, tmprec_Taskliste ist eine temp. Record-Variable auf Grundlage einer existierenden Tabelle, in der n Datensätze stehen. Diese Liste wird "Durchloopt". Für bestimmte DS nun kann es sein, daß ich den Satz der anderen tmp. Records initialisiere und partiell fülle und dann an die beschriebene Validierungsfunktion übergebe. Die Recs kommen dann valide und vervollständigt aus der Funktion zurück und werden weiterverarbeitet (oder aber die Funktion liefert eine Warnung und die Weiterverabeitung erfolgt halt nicht).

tmprec_Headerdata1, tmprec_Headerdata2 und tmprec_Lines1 sind die Input-Parameter für den Validierungs-Aufruf. Die Header-data sind in diesem Falle einzeilig, haben aber mehrere Felder, der Lines-Rec. kann dagegen auch mehrzeilig sein - aber alles gehört zu dem aktuell gerade im Loop aufgerufenen Datensatz aus der Taskliste.

Die Sourcetabellen sind deswegen wichtig, weil du offenbar in einer Schleife per INSERT temp. Records erzeugst, ohne jedoch den Primärschlüssel zu unterscheiden


So ist es. Der Wert, der in den Primary Key muß, wird im konkreten Fall erst durch die Validierungsfunktion ermittelt und steht noch nicht zu dem Zeitpunkt zur Verfügung, an dem der Record belegt wird. An dieser Stelle ist die Unterscheidung der Datensätze in dieser Variablen anhand des Primary Keys noch nicht notwendig, bzw. erfolgt anderweitig.


Letztlich wird an dieser Stelle mein Problem reduziert auf die Frage:

Muß ich, um einen temp. Record wirklich vollständig zu initalisieren, immer ein RESET, DELETEALL und CLEAR machen, oder gibt es einen Befehl, der das in einem Zuge erledigt?

Viele Grüße,

SF

20. Februar 2008 10:46

Hallo Natalie,

das Problem ist, daß ich einen komplexen Satz Daten von Extern bekomme, die ich in unserer Tabellenstruktur ablegen muß, d.h. ich bekomme verschiedene, fachlich zusammengehörende Entitäten, teilweise mit mehreren Datensätzen, die aber "zusammangehören". Die Qualität der Daten, die hereinkommen, sei zunächst undefiniert, und ich muß die Daten validieren und ggf. vervollständigen.

Ich verwende einen Satz von tmp. Record-Variablen, die die zukünftige Struktur schon spiegeln, und prozessiere nun den Input. Erst wenn die Daten vollständig validiert sind, schreibe ich sie dann auch wirklich in die Tabellen. Detektiere ich Inkonsistenzen oder fehlende, wichtige Parameter, die nicht aus dem Prozess heraus generiert werden können, so sollen die Daten komplett abgewiesen werden.

Zu Deinen Fragen:
Ja, tmprec_Taskliste ist eine temp. Record-Variable auf Grundlage einer existierenden Tabelle, in der n Datensätze stehen. Diese Liste wird "Durchloopt". Für bestimmte DS nun kann es sein, daß ich den Satz der anderen tmp. Records initialisiere und partiell fülle und dann an die beschriebene Validierungsfunktion übergebe. Die Recs kommen dann valide und vervollständigt aus der Funktion zurück und werden weiterverarbeitet (oder aber die Funktion liefert eine Warnung und die Weiterverabeitung erfolgt halt nicht).

tmprec_Headerdata1, tmprec_Headerdata2 und tmprec_Lines1 sind die Input-Parameter für den Validierungs-Aufruf. Die Header-data sind in diesem Falle einzeilig, haben aber mehrere Felder, der Lines-Rec. kann dagegen auch mehrzeilig sein - aber alles gehört zu dem aktuell gerade im Loop aufgerufenen Datensatz aus der Taskliste.

Die Sourcetabellen sind deswegen wichtig, weil du offenbar in einer Schleife per INSERT temp. Records erzeugst, ohne jedoch den Primärschlüssel zu unterscheiden


So ist es. Der Wert, der in den Primary Key muß, wird im konkreten Fall erst durch die Validierungsfunktion ermittelt und steht noch nicht zu dem Zeitpunkt zur Verfügung, an dem der Record belegt wird. An dieser Stelle ist die Unterscheidung der Datensätze in dieser Variablen anhand des Primary Keys noch nicht notwendig, bzw. erfolgt anderweitig.


Letztlich wird an dieser Stelle mein Problem reduziert auf die Frage:

Muß ich, um einen temp. Record wirklich vollständig zu initalisieren, immer ein RESET, DELETEALL und CLEAR machen, oder gibt es einen Befehl, der das in einem Zuge erledigt?

Viele Grüße,

SF

20. Februar 2008 13:05

lol nach einigem Grübeln fällt mir ein, warum deine (temp.) Recordvariablen unerwartet noch gefüllt sind:

Weil du in der Nachverarbeitungsfunktion (FillAndValidateRecords) offenbar den übergebenen Rec direkt abfragst, anstatt vorher (wie bei allen temp. Records ein Muss) ein TempRecord.FINDFIRST machst!

Nur über eine Abfrage des temp. Records (via GET, FIND, FINDSET oder FINDFIRST/LAST) lädst du dir wirklich in die Variable, was du zuvor mit INSERT eingefügt hast.
Ohne einen solchen Befehl bleibt im aktuellen Record so lange alles stehen, bis du ein CLEAR ausführst.

Der Fehler liegt also nicht in deinem veröffentlichten Code. Da kannst du die CLEARs auslassen.

20. Februar 2008 13:59

Ahaaaaa!

Gute Information!
Sehr gute Information! Werde ich grundsätzlich mal checken.

Trifft aber hier nicht das Problem:

Bleiben wir einfach auf dem Neveau des loops, in dem die Recs geleert werden und mit einem neuen Wert belegt werden - also noch VOR dem Funktionsaufruf.

Beim ersten Durchlauf ist der rec auch schön leer, ich weise die Werte u und das Key-Feld bleibt leer - ist dann auch wirklich leer.

Der rec geht in die Fkt., kommt daraus zurück und das Key-Feld ist korrekt mit einem dezidierten Wert belegt.

Nächster Loop:

Die Rec wird resettet, dann kommt das DeleteAll. Rec.INIT, die Rec-Felder werden zugeiwesen, nicht jedoch das Key-Feld. Dann der INSERT.

Und - schwupps - steht im Key-Feld dieNummer des letzten Durchlaufs.

Dieses "Gedächnis" töte ich halt mit dem CLEAR.

OK, davon abgesehen: Das RESET und anschließende DELETEALL läßt sich also nicht anders codieren (also durch eine Vokabel, die gerad beides gleichzeitig erledigt), sehe ich das richtig?

Viele Grüße,

SF

20. Februar 2008 14:03

INIT leert keine Primärschlüsselfelder. Das passiert erst mit dem CLEAR.

TempRec.RESET;
TempRec.DELETEALL;

ist richtig.

20. Februar 2008 14:06

OK, dann haben wir es.

Vielen Dank für eure Geduld und die Streicheleinheiten. :-D

Viele Grüße,

SF