![]() |
AW: FireDAC : Trigger geht nicht
FireDAC erkennt das ID-Feld als Primärschlüssel und fordert daher, dass es einen Wert erhält. Dieser wird aber erst auf dem Server (!) durch Deinen Trigger zugewiesen. Man muss FireDAC also dazu bringen, ein Feld, welches als "required" markiert ist, leer zum Server zu senden. Das geht entweder, indem man es als "AutoInc"-Feld deklariert (siehe Uwe) oder aber, indem man in den Update-Options die Eigenschaft "CheckRequired" auf FALSE setzt.
Bei Deinem Code kommt es gar nicht soweit, dass der Trigger angestossen werden könnte, weil FireDAC den Post-Request als unvollständig betrachtet und ablehnt. Die Daten erreichen den Server nicht einmal. |
AW: FireDAC : Trigger geht nicht
@nahpets : das mit der Exception (für mkinzler : Datenbank-Exception :mrgreen: ) hatte ich schon gemacht und deshalb gesehen, dass der Trigger tatsächlich nicht zuschlägt (natürlich für Insert ein BI-Trigger).
Und die Ursache für den Effekt ist tatsächlich genau das, was Uwe und Daniel angemerkt haben. Ich habe FireDAC eben nicht mitgeteilt, dass die ID ein über Trigger automatisch aktualisiertes Feld ist. Ich habe das jetzt nachgeholt und der ursprüngliche Fehler ist weg. Das haben sie aber trotz der Wichtigkeit unnötigerweise gut in OI-Untermenü versteckt bei Update-Options. Jetzt gibt es aber noch ein ähnliches Phänomen : Zitat:
|
AW: FireDAC : Trigger geht nicht
Hallo,
vielleicht hilft das ja. ![]() Also: Set TField.AutoGenerateValue to arAutoInc for an auto-incrementing field. This method does not create a TFDAutoIncField, it works with any field type, and may require additional field properties setup, like setting ProviderFlags, Required and ReadOnly. Zu spät ... (AutoInc) So, jetzt zeig mal deine Tabellenstruktur. Heiko |
AW: FireDAC : Trigger geht nicht
Tabelle ? Im Prinzip steht die oben schon, egal.
Code:
CREATE TABLE WG8 (
ID INTEGER NOT NULL, NR INTEGER NOT NULL, BEZ VARCHAR(25) DEFAULT '' NOT NULL ); ALTER TABLE WG8 ADD CONSTRAINT UNQ_WG8 UNIQUE (NR); ALTER TABLE WG8 ADD CONSTRAINT PK_WG8 PRIMARY KEY (ID); |
AW: FireDAC : Trigger geht nicht
Hallo zusammen,
ich hoffe, ich darf hier mal kurz "reingrätschen" ;-) : In dem Trigger steht: IF (NEW.ID IS NULL) THEN NEW.ID = GEN_ID(GEN_TEST_ID, 1); ...klingt im Prinzip gut, geht aber schief wenn durch irgendwas (z.B. FireDAC) die ID schon mit 0 (also numerisch 0, nicht dem Zustand NULL) vorbelegt wurde. besser: IF ((NEW.ID IS NULL) or (NEW.ID=0)) THEN NEW.ID = GEN_ID(GEN_TEST_ID, 1); oder auch (macht das selbe, nur etwas kürzer): IF (coalesce(NEW.ID,0) = 0) THEN // coalesce: falls NULL, nimm' das zweite Argument NEW.ID = GEN_ID(GEN_TEST_ID, 1); MMn: Entweder der Trigger in der DB feuert gar nicht (weil durch irgendwas in FireDAC das INSERT gar nicht erst bis zum Server durchkommt), oder er feuert zwar, macht dann aber nichts, weil die ID nicht NULL sondern 0 ist. lg, Frank P.S. gibt es hier so etwas wie einen Thread zur Vorstellung neuer User? ("Neu" bin ich zwar nicht mehr, aber zumindest hier gerade neu... :-D ) |
AW: FireDAC : Trigger geht nicht
Soweit ich informiert bin, haben Trigger in der DB Vorrang vor Client-Triggern. Im konkreten Fall hätte dann der Trigger, der die Id-Erzeugung im Generator anstößt, Vorrang vor dem im Firedac-Query eingestellten Defaultwert. In FireDac gebe ich an, welcher Generator für die Erzeugung des Primary-Key (den ich ebenfalls angebe) zuständig ist. FireDac führt das aber nur aus, wenn in der DB nicht bereits ein Trigger das Setzen dieses Wertes anstößt.
Zitat:
|
AW: FireDAC : Trigger geht nicht
Zitat:
2. das mit der ID ist schon geklärt, der Trigger scheint schon zu feuern. In externem IBExpert (bereits ca. 5mal gesagt) macht er das ja sowieso, aber auch in anderem eigenem Programm (allerdings mit FibPlus als Zugriffskomponenten) 3. Die Frage dreht sich nur noch darum, warum jetzt plötzlich der unique Key Ärger macht. Muss man das eventuell ähnlich einstellen, wie mit dem AutoInc-Feld ? Oder hängt das gar zusammen ? Ich sehe aber da nichts in FireDac, was irgendwie in diese Richtung gehen könnte. 4. Wie gesagt : bei leerer Tabelle schlägt der Insert fehl mit NR, die es noch gar nicht gibt. Und NR hat mit der ID nichts zu tun. Ist halt lediglich unique, was mein Programm besser sowieso der Datenbank im Fehlerfalle überlassen sollte. @Perlsau : Davon ging ich auch aus. Der DB muss aber offensichtlich das als AutoInc zu behandelnde Feld mitgeteilt werden. Die Frage lautet jetzt also, was FireDac da weshalb genau macht. Warum interessiert sich FireDac überhaupt um einen unique Key ? Trigger/ID ist vorerst erledigt ! Also nochmals : der Trigger geht definitiv richtig ! Und der nicht vorhandene unique landet nicht in der DB wegen
Code:
Die Nr. 101 ist doch gar nicht da !
Problematic Key is ("NR" = 101
|
AW: FireDAC : Trigger geht nicht
geth die Meldung noch weiter? Ich seh da "(" auf nicht zu. Ist die Nummer 101 vollständig oder ist da was abgeschnitten?
Mit welcher Aktion erzeugst Du diesen Fehler? Offenbar ja mittels Delphiprogramm. Welche Werte stehen vor dem Post im Record? Ist "Nr" belegt oder leer? Leer sollte es nicht sein, da es not null definiert ist. |
AW: FireDAC : Trigger geht nicht
Sicher, dass die 101 noch nicht da ist?
Ausgehend von den Quelltextfragmenten, kann es die 101 nur einmal geben. Zumindest gehe ich mal davon aus, dass du da eine For-Schleife mit sowas wie
Delphi-Quellcode:
hast. Wenn dem so ist, warum wird dann nicht schon bei Nr. 100 gemoppert?
for i := 0 to n
Wenn i bei 1 beginnt, hieße das aber, dass bereits der erste Satz als Schlüsselverletzung angesehen wird. Dies erscheint mir dann aber doch ziemlich schräg, könnte aber bedeuten, dass irgend etwas konfigurationstechnisch dafür sorgt, dass jeder Datensatz mindestens zweimal (aus Sicht der Datenbank) dort ankommt. Was passiert, wenn Du (vorerst) nach jedem Satz mal ein Commit machst? Quasi
Delphi-Quellcode:
Zumindest müsstest Du bei einem satzweisen Commit ja dann nachschauen können, ob schon 'ne 101 da ist. Wenn nicht, dann muss das Problem bei FireDac liegen.
if i mod 1 = 0 then begin
Eventuell könntest Du den Quelltext mal ein bisserl umbauen:
Delphi-Quellcode:
Wie oft bekommst Du hier i = 1 zu sehen? Denn das müsste ja eigentlich zu dem Fehler führen.
DM.DS.Insert;
DM.DS.FieldByName('NR').AsInteger := i + 100; DM.DS.FieldByName('BEZ').AsInteger := i; try DM.DS.Post; except on e : Exception do begin DM.DS.Cancel; mem1.Lines.Add(Format('i = %d - %s'[i,e.Message])); end; end; Zugegeben sind mein Vorschläge gerade nur reines stochern im Nebel, darfst sie von daher gerne ignorieren ;-) |
AW: FireDAC : Trigger geht nicht
Hallo zusammen,
@Hansa: ich bin da "gebranntes Kind": wenn <irgendwas> mit IBExpert geht, dann heißt das noch lange nicht, dass es mit Firebird per se geht... (sorry, Holger... ;-) "Der Trigger scheint zu feuern"... Vergiss' das. Lege einen neuen Generator an, der NUR im Trigger erhöht wird. Wenn der nach deinem Test erhöht wurde, dann wurde der Trigger gefeuert. Sonst nicht. ("Generators run outside of transaction control!") (Ob die Transaktion danach dann vlt. einem Rollback zum Opfer gefallen ist, weisst Du dann aber immer noch nicht ;) ) Die Sache mit dem Unique Key ist noch mal eine ganz andere Baustelle. Ohne das Umfeld genauer zu kennen, kann ich nur mutmaßen: wenn die DB meckert, daß es zum Zeitpunkt des Inserts schon einen Datensatz mit NR=<x> gab, dann wird das wohl so gewesen sein... ;) Vlt. noch eine andere Instanz des Programms? Nicht-COMMITtete Transaktion? Die Transaktionen in Fb funktionieren, dafür lege ich meine Hand in's Feuer(!). Die Generatoren/Sequenzen auch. Wenn im Zusammenspiel zwischen Programm und Fb-Server etwas nicht funktioniert, liegt das Problem erfahrungsgemäß irgendwo in der Mitte ;) lg, Frank |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz