AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)
Thema durchsuchen
Ansicht
Themen-Optionen

FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

Ein Thema von Kostas · begonnen am 2. Sep 2022 · letzter Beitrag vom 6. Sep 2022
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#11

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 2. Sep 2022, 17:52
Zitat:
active before insert position 0
...das heißt in der DB auch Before. Ist mir noch nicht untergekommen. Für mein Verständis brauche ich die neue "ID" erst dann, wenn der Datensatz geschrieben wurde.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#12

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 2. Sep 2022, 18:02
Was vom Trigger kommt, dass kann FireDAC garnicht wissen, da es vor ihm versteckt ist und es auch erst bei POST in der DB ausgeführt wird.

Wie wäre es mit generated by ?
https://stackoverflow.com/questions/...ebird-database


Natürlich kannst du im OnAfterInsert ein SELECT gen_id(gen_bankdatenschulungen_id,1) machen, die ID abfragen und deinem Field zuweisen.



Bei PostgreSQL stehen die Generatoren mit in den DEFAULT-Werten Felder.
Im AfterInsert wird bei uns ein SELECT mit den Defaults zusammengebaut (die SQL-Statements davon kann man ja von der DB abfragen), ausgeführt und den Fields zugewiesen,
damit die Nutzer bereits in den Edits/Grids die Werte sehen, welche sonst eigentlich erst beim POST reinkommen kommen würden.
$2B or not $2B

Geändert von himitsu ( 2. Sep 2022 um 18:11 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#13

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 2. Sep 2022, 20:36
Der Kernpunkt ist hier UpdateOptions.FetchGeneratorsPoint = gpImmediate . Das sorgt laut Dokumentation dafür, dass die ID schon beim Insert bzw. Append ermittelt wird.
Zitat:
Controls the moment when the next generator value is fetched.

Use FetchGeneratorsPoint to specify the moment when the next generator value is fetched from a database and assigned to an auto-incremental field. The default value is gpDeferred.

The next generator value will be fetched from a generator, specified by the TFDUpdateOptions.GeneratorName/TFDAutoIncField.GeneratorName properties and assigned to the auto-incremental fields, which have pfInUpdate in ProviderFlags.

An auto-incremental field is:

A field of the TFDAutoIncField class.
A field whose name is specified in AutoIncFields.
A field with TField.AutoGenerateValue = arAutoInc.
Generators are supported by InterBase and Firebird. Sequences are supported by Oracle and PostgreSQL DBMSs. For other DBMSs this property has no meaning. The value can be one of the following:

Code:
Mode         Description

gpNone       Do not fetch generator values.
gpImmediate  Fetch values right after starting to append a new record. Normally, this is the value for the TDataSet.Insert or Append methods.
gpDeferred   Fetch values right before posting a new record to a database. Normally, this is the value for the TDataSet.Post or ApplyUpdates methods.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
jobo

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

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 3. Sep 2022, 14:43
Ein AutoInc Field zur Befüllung eines PK wird aus Sicht der DB entweder über
  • den Spaltentyp geregelt oder
  • über einen Trigger mit Hilfe eines Generators oder
  • nur über einen Generator.

Anscheinend gibt es in
<=V. 2.5:
nur Generatoren, diese können mit Triggern zur Befüllung kombiniert werden
V. 3:
die Spaltendefinition "by default as identity primary key"
V. 4:
die Spaltendefinition "always as identity primary key"

zu "<=2.5" bzw. überall dort wo ein Trigger im Einsatz ist:
Die Existenz und Nutzung eines Triggers sagt nichts über die zwangsweise Nutzung des Generatorwertes. Trigger sind häufig so geschrieben, dass sie einen mitgegebenen Wert (durch das Insert) verwenden. (siehe unten)

zu 3: "..by default.." verhält sich analog zum häufig so wie oben beschriebenen Triggeraufbau, es setzt nur den Defaultwert mittels einer (internen) Sequenz, dieser bleibt aber überschreibbar. Also gleiche Funktionalität wie zuvor, nur ohne den selbst erstellten Trigger.

zu 4: ".. always .." verwendet immer den internen Sequenzwert, benötigt auch keinen Trigger.

Nach der Befüllung nutzt man die Rückgabe/Abfrage des Generators zur Weiterverwendung dieses Wertes bspw. in FKs. Wird ein Generator verwendet, dann per fragt man den letzten Wert so ab:
Code:
SELECT GEN_ID( GeneratorName, 0 ) FROM RDB$DATABASE;
(oder innerhalb eines anderen SQL Statements)
Seit FB 2.0 kann auch gleich per RETURNING im Insert Statement der Wert zurückgegeben werden.
Das ist der sicherste und bequemste Weg, diesen Wert zu erfahren, weil er unabhängig von der Erzeugung ist.

Das bis jetzt beschriebene Verhalten muss sich alles per SQL in der Kommandozeile nachvollziehen lassen (Es muss natürlich entsprechend in den Tabellen richtig definiert sein).

Die FD Kompos und ihr Verhalten kenne ich nicht. (Was ich hier schreibe, habe ich nicht in Delphi validiert) Sie müssen aber alles oben beschriebene berücksichtigen und können nicht tiefer eingreifen, als es mit bloßem SQL geht. Sie bieten aber "Komfortproperties" zur einfacheren Handhabung.
Wenn man in den Properties einen Generatornamen angeben kann, dann sollte es für das gewünschte Verhalten auch gemacht werden.
Ab FB 3 sollte es nicht nötig sein, einen Generator anzulegen, wenn die Spalte mit "..generated.." definiert wurde. (Mir ist nicht klar, ob die FD Kompos das 'generated' Feature überhaupt berücksichtigen)

Zeitpunkt (Before/After- für DB und Delphi)
Alles was die DB macht (an Werten ändert/ergänzt), kann Delphi (im Prinzip egal welcher Client) nicht wissen, solange das Insert nicht abgeschlossen ist. (Ausnahme, es gibt keine Trigger, keine Generated Spalten und auch keine Defaults, dann ist bei einem simplen Insert aus dem Client auch das Ergebnis bekannt, weil identisch). Eine zeitliche Unterscheidung gibt es dabei nur mittels Trigger. Das wird ja auch beim Insert Trigger "before insert" für "new.IDcolumn" genutzt.

Ein Client kann eigentlich nur 2 Dinge tun:
Entweder er holt selbst einen neuen Generatorwert, bevor das Insert erfolgt und übergibt den Wert an das Insert.
Oder er holt nach dem Insert den aktuellen Generatorwert und stellt ihn innerhalb der Komponente zur Weiterverwendung (Anzeige, ..) zur Verfügung.

Wenn man nach dem Insert einen Wert aus dem Client überschreibt- wie @kostas es darstellt-, sollte der auch gezielt gepostet werden, sonst geschieht das Posten gar nicht oder ungezielt irgendwann implizit, man zerstört zu einem ungewissen Zeitpunkt also den Originalwert. Damit verlässt man die Vorgaben, die DB Seitig festgelegt wurden. Es handelt sich aus DB Perspektive dann um ein Update.

Der von @kostas gepostete Trigger
[code]
CREATE OR ALTER trigger bankdatenschulungen_bi for bankdatenschulungen
active before insert position 0
as
begin
if (new.bankdatenschulungenid is null) then
new.bankdatenschulungenid = gen_id(gen_bankdatenschulungen_id,1);
end
[code]
setzt die ID new.bankdatenschulungenid nur unter der Bedingung, dass das Feld nicht bereits vorbelegt ist(oder auch mitgeliefert wurde- normalerweise durch das Insertstatement). Hat die Spalte also später einen Wert, den man separat angegeben hat, ist es in diesem Fall dem bedingt arbeitenden Trigger zu verdanken und hat erstmal nichts mit Client Komponenten zu tun. Oder der separate Wert kommt durch ein Update, dann ist der Insert Trigger sowieso nicht beteiligt.

Ich habe dazu fiddles angelegt. Diese klären natürlich nicht das Verhalten im Client, verdeutlichen aber hoffentlich so gut es geht das DB Verhalten- welches unumgänglich ist. Bei Interesse bitte Bescheid sagen.
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#15

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 3. Sep 2022, 17:01
Deine Beschreibungen sind zwar gut fundiert und umfangreich, decken aber das im Originalpost verwendete Verfahren nicht ab. Dabei werden die IDs zwar über einen Generator in der DB erzeugt, aber von der Client-Komponente an den Server übertragen. Das hat den Vorteil, und genau darum geht es hier gerade, dass die IDs dem Programm schon vor dem Speichern des Datensatzes in der DB bekannt sind.

Grundsätzlich ist das ein von FireDAC unterstütztes Vorgehen. Ob man es selbst anders realisieren würde steht nicht zur Debatte, weil wir die konkreten Anforderungen nicht kennen.

Es geht also schlichtweg darum, ob und wenn ja welche einzelne Einstellungen in den Komponenten nicht korrekt sind oder ob womöglich ein Bug in der verwendeten Delphi-Version vorliegt, der in späteren Versionen behoben wurde.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
jobo

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

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 3. Sep 2022, 17:36
..Dabei werden die IDs zwar über einen Generator in der DB erzeugt, aber von der Client-Komponente an den Server übertragen. Das hat den Vorteil, und genau darum geht es hier gerade, dass die IDs dem Programm schon vor dem Speichern des Datensatzes in der DB bekannt sind.
Naja, das wollte ich hiermit zum Ausdruck bringen:

Zitat:
Ein Client kann eigentlich nur 2 Dinge tun:
Entweder er holt selbst einen neuen Generatorwert, bevor das Insert erfolgt und übergibt den Wert an das Insert.
Oder er holt nach dem Insert den aktuellen Generatorwert und stellt ihn innerhalb der Komponente zur Weiterverwendung (Anzeige, ..) zur Verfügung.
Ich hoffe, die Beschreibung dient ansonsten dem allgemeinen Verständnis.
Gruß, Jo
  Mit Zitat antworten Zitat
Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.099 Beiträge
 
Delphi 10 Seattle Enterprise
 
#17

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 3. Sep 2022, 17:38
Der Kernpunkt ist hier UpdateOptions.FetchGeneratorsPoint = gpImmediate . Das sorgt laut Dokumentation dafür, dass die ID schon beim Insert bzw. Append ermittelt wird.

...
Code:
Mode         Description

gpNone       Do not fetch generator values.
gpImmediate  Fetch values right after starting to append a new record. Normally, this is the value for the TDataSet.Insert or Append methods.
gpDeferred   Fetch values right before posting a new record to a database. Normally, this is the value for the TDataSet.Post or ApplyUpdates methods.
[/QUOTE]


Die Doku habe ich gelesen und so eingestellt, meine ich zumindest. Ich hätte erwartet dass bei onBeforePost den Generatorwert bereits gesetzt ist. Genau das ist nicht der Fall. Auch interessant ist, dass das PK Feld, auch wenn ich den Wert setze, in der DB immer als null übertragen wird. Deshalb feuert der Trigger der DB und setzt den PK Wert. Ich habe ein Demo Programm erstelle auf die gleiche DB und die Connection über IBObjects erstellt. Hier ist der Generator des PKs bei OnBeforePost vorhanden und auch so zur DB übertragen. Es liegt also nicht an der DB sondern an irgend einer Einstellung in FireDac. Ich verwende übrigens Delphi 11.1
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#18

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 3. Sep 2022, 18:05
Wie schon gesagt ... das KANN auch garnicht vom FireDAC hier so gemacht werden.

Ob und was IN einer Trigger-Funktion drin steht, dass weiß es nicht und kann es auch nicht sicher wissen (Funktionsinhalt parsen und Funktionsweise analysieren), also kann es auch nicht im AfterInster genutzt werden.

Nur was AN dem Tabellen-Feld deklariert ist, dass kann es auslesen und verwenden.

Bei dem "always" könnte es zwas die Sqeuenz abfragen, aber es wäre "Sinnlos", weil es beim Speichern wieder überschrieben würde. (falls zwischendurch jemand anderes was gemacht hat, dann auch noch mit einem anderen Wert)
$2B or not $2B

Geändert von himitsu ( 3. Sep 2022 um 18:09 Uhr)
  Mit Zitat antworten Zitat
jobo

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

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 3. Sep 2022, 19:02
Wie gesagt, es ging mir um die DB Seite. Wenn (dem Nutzer) klar ist, wie das funktioniert, klärt sich vielleicht auch die Client Seite.
Wenn man die "generated" Variante wählt, braucht es eh keinen Trigger und keine eigenen Generatoren. Und die Sequenzen, die in dem Fall dann genutzt werden, sind ja erstmal gar nicht transparent.
"Generated" kann dadurch am ehesten mit Returning Clause genutzt werden.
Aber vielleicht beherrschen das die FD Kompos auch, weiß ich nicht, möglich wäre es.
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#20

AW: FireDac den AutoInc value in onBeforePost abfragen. (ist immer -x)

  Alt 3. Sep 2022, 19:31
Auch interessant ist, dass das PK Feld, auch wenn ich den Wert setze, in der DB immer als null übertragen wird.
Das ist zumindest ein Hinweis, wo das Problem liegen könnte.

Kannst du ein kleines Beispielprogramm mit denselben FireDAC Einstellungen machen?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 12:17 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