Entwickler-Ecke

Datenbanken - [FIBDataSet] - Refresh vs. FullRefresh


Der Jan - Do 01.12.05 12:36
Titel: [FIBDataSet] - Refresh vs. FullRefresh
Hallo,

ich schon wieder :roll:

Ich habe eine kleine Personal-Verwaltung geschrieben, die soweit auch gut funktioniert, allerdings habe ich ein Problem beim Refreshen von FIBDataset.

Es wird in die Tabelle PERSONAL ein neuer Record mit Append eingefügt.
nachdem im Formular die Daten eigegeben wurde, schreibe ich den Record in die Tabelle

Delphi-Quelltext
1:
2:
dsetPers.Post;
dsetPers.Refresh;

Es gibt in der Tabelle ein Feld PERSONALID, welches mittels Trigger/Generator automatisch erzeugt wird. Das funktioniert auch alles wunderbar, die Werte stehen in der Tabelle (Kontrolliert mit IBExpert)

Jetzt kann man dem Record noch Dokumente hinzufügen (Passbild etc.), die in einer anderen Tabelle BLOBS gespeichert werden. Das mach ich über einen FIBQuery.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
with qryPhoto do begin
  SQL.Clear;
  SQL.Add('INSERT INTO "BLOBS" (DATA, PERSONALID, PHOTO, ORIGNAME, ORIGSIZE)');
  SQL.Add('VALUES (:DATA, :PERSONALID, :PHOTO, :ORIGNAME, :ORIGSIZE)');
  ParamByName('DATA').LoadFromStream(ms);
  ParamByName('PERSONALID').AsInteger := dsetPers.FieldValues['PERSONALID'];
  ParamByName('PHOTO').AsString := '1';
  ParamByName('ORIGNAME').AsString := ExtractFileName(sName);
  ParamByName('ORIGSIZE').AsInteger := ms.Size;
  ExecQuery;
end;

Das funktioniert soweit auch noch, es sei denn, man versucht, ein Dokument einem neu eingefügten Record zuzuweisen. In diesem Fall ist der Wert das Feldes PERSONALID Null. Trotz Refresh.(siehe oben) Mache ich statt dessen dsetPers.FullRefresh, funktioniert es. Nur FullRefresh tut das für alle Records, was ab einer gewissen Anzahl nicht mehr wirklich akzeptabel ist.
Wo könnte hier der Fehler liegen?


alex517 - Do 01.12.05 13:12

Hi Der Jan,

du hast die Möglichkeit die die neue ID noch vor dem Append des neuen Pers-Datensatzes geben zu lassen.
Damit ist diese ID sofort auch für die abhängigen Daten verfügbar.
Das kann man auf zwei Wegen erreichen.

1) in dsetPersNewRecord oder dsetPersBeforePost:

Delphi-Quelltext
1:
2:
3:
  
if dsetPersPERSONID.AsInteger = 0 then
  dsetPersPERSONID.AsInteger := dsetPers.Database.Gen_Id('GEN_PERS'1);


oder

2) mit Hilfe der FIBDataSet.AutoUpdateOptions mit GeneratorName, GeneratorStep und WhenGetGenID.

alex


Der Jan - Do 01.12.05 15:06

Hallo,

erstmal Danke für den Tip. Das wars im Wesentlichen. :idea:
Ich habe in Beforepost oder OnNewRecord geschrieben:

Delphi-Quelltext
1:
2:
3:
    with dmodMain.dsetPers do
      if(FieldByName('PERSONALID').AsInteger = 0then
        FieldByName('PERSONALID').AsInteger := Database.Gen_Id('GEN_PERSONAL_ID'1);


Bei OnNewRecord hat man noch den Vorteil, das man z.B. das Bild einfügen kann, bevor der Datenssatz in der Tabelle PERSONAL steht.

Funktioniert soweit. Man muß aber in der DB den Trigger für die automatische ID-Generation ausschalten sonst gibts einen Fehler. Siehe Anhang

Besten Dank nochmal!


Der Jan - Do 01.12.05 15:08

Irgendwie krieg ich den Screenshot nicht mitgeschickt.... :(

Er meckert wegen einer ForeignKey-Constraint-Verletzung


alex517 - Do 01.12.05 15:25

user profile iconDer Jan hat folgendes geschrieben:
. Man muß aber in der DB den Trigger für die automatische ID-Generation ausschalten sonst gibts einen Fehler. Siehe Anhang


Auschalten muß nicht sein:

SQL-Anweisung
1:
  IF (NEW.ID IS NULLTHEN NEW.ID = GEN_ID(GEN_PERS_ID,1);                    


Das Problem mit der ForeignKey-Constraint-Verletzung liegt evt. daran, dass der neue Pers-Datensatz
noch nicht commited ist. Damit ist er für andere nicht sichtbar.

alex


Der Jan - Do 01.12.05 17:34

Hm, komisch, genau so sah mein Trigger eigentlich aus... :?
Naja, wer weiß... Es funktioniert jetzt jedenfalls....