Autor |
Beitrag |
NOS
Beiträge: 183
Erhaltene Danke: 2
Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 19.4 - Sydney
|
Verfasst: Di 09.04.19 21:02
Hallo zusammen,
ich möchte auf Knopfdruck Daten aus Formularen in eine Firbird DB schreiben. Die Daten sind getrennt zwischen Auftragsdaten und Produktdaten.
Wenn ich nun zunächst die Hauptdaten der DB in die Auftragsdaten Tabelle schreibe, möchte ich mir im Anschluss an das POST die erzeugte ItemID auslesen und diese für jedes Produkt in die Produktdatentabelle schreiben. Allerdings ist die ItemID immer 1, obwohl ich einen Generator etc. erzeugt habe. Der ItemID Wert ist für den ersten Datensatz 1, was also stimmt und der Generator funktioniert somit. Nur wenn ich die Routine 2 mal hintereinander aufrufe funktioniert es nicht. Was mache ich falsch?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| ItemDBGrid.DataSource.DataSet.Append; if ItemDBGrid.DataSource.DataSet.State = dsInsert then begin ItemDBGrid.DataSource.DataSet.FieldValues['ITEMTYPE'] := Integer(cbItemType.ItemIndex); ItemDBGrid.DataSource.DataSet.FieldValues['ITEMSUBJECT'] := edItemSubject.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMCUSTOMERADDRLINE1'] := edRecipientLine1.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMCUSTOMERADDRLINE2'] := edRecipientLine2.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMCUSTOMERADDRLINE3'] := edRecipientLine3.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMCUSTOMERADDRLINE4'] := edRecipientLine4.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMCUSTOMERADDRLINE5'] := edRecipientLine5.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMCUSTOMERADDRLINE6'] := edRecipientLine6.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMNUMBER'] := edItemNumber.Text; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMDATE'] := edItemDate.Date; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMDESCRIPTION'] := memoItemDescriiption.Text; ItemDBGrid.DataSource.DataSet.FieldValues['OVERALLNETTO'] := edOverallNetto.FloatValue; ItemDBGrid.DataSource.DataSet.FieldValues['OVERALLINCLUDEDTAX'] := edOverallIncludedTax.FloatValue; ItemDBGrid.DataSource.DataSet.FieldValues['OVERALLBRUTTO'] := edOverallBrutto.FloatValue; ItemDBGrid.DataSource.DataSet.FieldValues['OVERALLTAX'] := edItemTaxRate.FloatValue; ItemDBGrid.DataSource.DataSet.Post; end else begin ItemDBGrid.DataSource.DataSet.Cancel; end; ItemDBGrid.DataSource.DataSet.Refresh; ItemId := ItemDBGrid.DataSource.DataSet.FieldValues['ITEMID']; |
Moderiert von Th69: Topic aus Datenbanken (inkl. ADO.NET) verschoben am Mi 10.04.2019 um 08:24
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 09.04.19 21:24
Das sieht eher weniger nach .Net Code aus. Eher nach klassischem Delphi.
Warum sollte nach einem Post Richtung Datenbank plötzlich der Generator Value in einem Wert des DataSets stecken?
Sollte man nicht den Generator Wert vor dem Insert holen in seinen Datensatz schreiben und dann posten?
Wenn es bei dir anders läuft solltest du erklären warum bzw. für die Frage das richtige Subforum wählen wenn das was Delphi spezifisches ist.
Für diesen Beitrag haben gedankt: NOS
|
|
NOS
Beiträge: 183
Erhaltene Danke: 2
Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 19.4 - Sydney
|
Verfasst: Di 09.04.19 21:44
Ja ... sorry ... es geht um Delphi ... kann ich den Post verschieben oder soll ich dort neu posten?
Ich arbeite sonst nicht mit einem DBGrid und daher ging ich davon aus dass der Post nach dem Append den Record in die DB schreibt, das Refresh diesen im Dataset aktualisiert und ich daraus dann den ItemID sprich Generatorwert auslesen kann.
Wenn ich das händisch mache, wann wird denn der Generatorwert erhöht, wenn nicht beim Post?
P.S. Danke fürs Verschieben ins richtige Subforum
|
|
Th69
Beiträge: 4785
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Sa 13.04.19 12:06
So wie Ralf geschrieben hat, mußt du selber den ID-Wert aus dem Generator auslesen und setzen:
Delphi-Quelltext 1: 2:
| newId := ...; ItemDBGrid.DataSource.DataSet.FieldValues['ITEMID'] := newID; |
s. z.B. Databases - Firebird Generators
Alternativ einen Trigger dafür erzeugen: How to create an autoincrement column?
PS: Die einzelnen ItemDBGrid.DataSource.DataSet-Zielen sehen 'ugly' aus (besser z.B. with oder Variable dafür anlegen und benutzen).
Zuletzt bearbeitet von Th69 am Sa 13.04.19 12:13, insgesamt 1-mal bearbeitet
|
|
NOS
Beiträge: 183
Erhaltene Danke: 2
Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 19.4 - Sydney
|
Verfasst: Sa 13.04.19 12:12
Oh ... sorry ... dann kam das falsch rüber ... es ist ein Generator mit trigger in der DB ... drum kam ich darauf dass ich nach dem Post auch die ItemID auslesen kann.
Hier mal der Code aus dem Erzeugen der DB:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| sqlexec := 'CREATE TABLE ItemTable(ITEMID BIGINT, ' + 'ITEMTYPE BIGINT, ' + 'ITEMCUSTOMER VARCHAR(1000), ' + 'ITEMSUBJECT VARCHAR(1000), ' + 'ITEMCUSTOMERADDRLINE1 VARCHAR(1000), ' + 'ITEMCUSTOMERADDRLINE2 VARCHAR(1000), ' + 'ITEMCUSTOMERADDRLINE3 VARCHAR(1000), ' + 'ITEMCUSTOMERADDRLINE4 VARCHAR(1000), ' + 'ITEMCUSTOMERADDRLINE5 VARCHAR(1000), ' + 'ITEMCUSTOMERADDRLINE6 VARCHAR(1000), ' + 'ITEMNUMBER VARCHAR(1000), ' + 'ITEMDATE TIMESTAMP,' + 'ITEMDESCRIPTION BLOB SUB_TYPE TEXT, ' + 'OVERALLNETTO FLOAT, ' + 'OVERALLINCLUDEDTAX FLOAT, ' + 'OVERALLBRUTTO FLOAT, ' + 'OVERALLTAX FLOAT ' + ');'; ExecSQL(sqlexec); sqlexec := 'CREATE UNIQUE INDEX IDX_ID ON ItemTable(ITEMID);'; ExecSQL(sqlexec); sqlexec := 'CREATE GENERATOR genID;'; ExecSQL(sqlexec); sqlexec := 'SET GENERATOR genID TO 0;'; ExecSQL(sqlexec); sqlexec := 'CREATE TRIGGER trigID FOR ItemTable ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.ITEMID IS NULL) THEN NEW.ITEMID = GEN_ID(genID, 1); END;'; ExecSQL(sqlexec); |
Kann es sein dass das DataSet oder das DBGrid nicht auf den neuen Record zeigt nach dem Append und ich deshalb immer den falschen Wert erhalte?
|
|
Th69
Beiträge: 4785
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Sa 13.04.19 14:00
Dann debugge es doch mal und schau dir die anderen FieldValues an (evtl. auch mal die RecNo überprüfen).
Laut TDataSet.Refresh wird der Cursor bei einem unidirektionalen DataSet wieder auf den ersten Eintrag gesetzt (das kannst du mittels IsUniDirectional überprüfen).
|
|
NOS
Beiträge: 183
Erhaltene Danke: 2
Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 19.4 - Sydney
|
Verfasst: Sa 13.04.19 18:06
Also unidirektional ist das DataSet nicht ...
wenn ich mit einer leeren DB anfange ist die RecNo nach dem ersten Post auf 1 und der Datensatz ist ok ...
nach dem 2ten Post ist die RecNo auf 2 aber die Values sind die vom ersten Record ...
TDataSet.Last bringt leider auch nichts ...
Was mache ich grundlegend falsch?
|
|
icho2099
Beiträge: 101
Erhaltene Danke: 12
WIN XP, WIN 7, WIN 10
Delphi 6 Prof, Delphi 2005, FPC
|
Verfasst: So 14.04.19 09:03
|
|
NOS
Beiträge: 183
Erhaltene Danke: 2
Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 19.4 - Sydney
|
Verfasst: Mo 15.04.19 13:04
@icho2099
So war mein Grundgedanke zur Lösung ... geht es denn generell nicht mit Append, Post? Kann ich mir gar nicht vorstellen.
|
|