Autor Beitrag
NOS
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: 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?

ausblenden 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;
            // check if we are in insert mode
            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;
            // add product data to the db
            // get itemid
            ItemId := ItemDBGrid.DataSource.DataSet.FieldValues['ITEMID'];


Moderiert von user profile iconTh69: Topic aus Datenbanken (inkl. ADO.NET) verschoben am Mi 10.04.2019 um 08:24
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4431
Erhaltene Danke: 906


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4049
Erhaltene Danke: 838

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Sa 13.04.19 12:06 
So wie Ralf geschrieben hat, mußt du selber den ID-Wert aus dem Generator auslesen und setzen:
ausblenden Delphi-Quelltext
1:
2:
newId := ...; // read from generator
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: 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:

ausblenden volle Höhe 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:
30:
31:
32:
     // create empty offers table
     sqlexec := 'CREATE TABLE ItemTable(ITEMID BIGINT, ' +                               // id
                                       'ITEMTYPE BIGINT, ' +                             // item typ (Rechnung,Angebot,Kostenvoranschlag,Bestellung)
                                       'ITEMCUSTOMER VARCHAR(1000), ' +                  // kunde als text für die listen
                                       'ITEMSUBJECT VARCHAR(1000), ' +                   // betreff text
                                       'ITEMCUSTOMERADDRLINE1 VARCHAR(1000), ' +         // adresszeile 1
                                       'ITEMCUSTOMERADDRLINE2 VARCHAR(1000), ' +         // adresszeile 2
                                       'ITEMCUSTOMERADDRLINE3 VARCHAR(1000), ' +         // adresszeile 3
                                       'ITEMCUSTOMERADDRLINE4 VARCHAR(1000), ' +         // adresszeile 4
                                       'ITEMCUSTOMERADDRLINE5 VARCHAR(1000), ' +         // adresszeile 5
                                       'ITEMCUSTOMERADDRLINE6 VARCHAR(1000), ' +         // adresszeile 6
                                       'ITEMNUMBER VARCHAR(1000), ' +                    // id-nummer (re-nr,an-nr etc.)
                                       'ITEMDATE TIMESTAMP,' +                           // datum
                                       'ITEMDESCRIPTION BLOB SUB_TYPE TEXT, ' +          // beschreibung
                                       // sales and price
                                       'OVERALLNETTO FLOAT, ' +                          // nettopreis
                                       'OVERALLINCLUDEDTAX FLOAT, ' +                    // enthaltene steuer
                                       'OVERALLBRUTTO FLOAT, ' +                         // bruttopreis
                                       // tax
                                       'OVERALLTAX FLOAT ' +                             // steuersatz
                                       ');';
     ExecSQL(sqlexec);
     // create index on ID
     sqlexec := 'CREATE UNIQUE INDEX IDX_ID ON ItemTable(ITEMID);';
     ExecSQL(sqlexec);
     // create autoincrement OfferID
     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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4049
Erhaltene Danke: 838

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 83
Erhaltene Danke: 9

WIN XP, WIN 7, WIN 10
Delphi 6 Prof, Delphi 2005
BeitragVerfasst: So 14.04.19 09:03 
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: 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.