Datensatz in Datenbank



  • Hallo allerseits,

    mal wieder stehe ich vor einem Rätsel. In einem Gemeinschaftsprojekt ist ein Fehler aufgetaucht. Ich hoffe ich kann ihn beschreiben, der Fehler liegt in einem Programmteil, den ein Kollege erstellt hat... Es geht um den Eintrag eines Datensatz in eine Datenbank. Den Datensatz stelle ich in meinem Programmteil in einer Struktur zur Verfügung:

    struct
    {
    	AnsiString FeldA;
    	AnsiString FeldB;
    
    	union
    
    	{
    		unsigned char Stelle[64];
    		long Wert[16];
    	}Ergebnisse;
    
    	AnsiString ZusatzA, ZusatzB, ZusatzC;
    }DBStruktur;
    

    Der Kollege schreibt den Datensatz dann mit einem "DataModule" (?) in eine Datenbanktabelle:

    Table1->InsertRecord(ARRAYOFCONST((LfdNummer,
                                 DBStruktur.FeldA,
                                 DBStruktur.FeldA,
                                 (float)DBStruktur.Ergebnisse.Wert[0],
                                 (float)DBStruktur.Ergebnisse.Wert[1],
                                 (float)DBStruktur.Ergebnisse.Wert[2],
                                 (float)DBStruktur.Ergebnisse.Wert[3],
                                 (float)DBStruktur.Ergebnisse.Wert[4],
                                 (float)DBStruktur.Ergebnisse.Wert[5],
                                 (float)DBStruktur.Ergebnisse.Wert[6],
                                 (float)DBStruktur.Ergebnisse.Wert[7],
                                 (float)DBStruktur.Ergebnisse.Wert[8],
                                 (float)DBStruktur.Ergebnisse.Wert[9],
                                 (float)DBStruktur.Ergebnisse.Wert[10],
                                 (float)DBStruktur.Ergebnisse.Wert[11],
                                 (float)DBStruktur.Ergebnisse.Wert[12],
                                 (float)DBStruktur.Ergebnisse.Wert[13],
                                 (float)DBStruktur.Ergebnisse.Wert[14],
                                 (float)DBStruktur.Ergebnisse.Wert[15])));
    

    wobei die Felder der Datenbanktabelle über die Datenbankoberfläche von C++Builder 3 so angelegt sind:

    Name         Typ         Größe
    1     LfdNr        Integer
    2     EintragA     Alpha       10
    3     EintragB     Alpha       8
    4     Wert1        Numerisch
    5     Wert2        Numerisch
    6     Wert3        Numerisch
    7     Wert4        Numerisch
    8     Wert5        Numerisch
    9     Wert6        Numerisch
    10    Wert7        Numerisch
    11    Wert8        Numerisch
    12    Wert9        Numerisch
    13    Wert10       Numerisch
    14    Wert11       Numerisch
    15    Wert12       Numerisch
    16    Wert13       Numerisch
    17    Wert14       Numerisch
    18    Wert15       Numerisch
    19    Wert16       Numerisch
    20    ReserveA     Alpha       20
    21    ReserveB     Alpha       20
    22    ReserveC     Alpha       20
    

    Soweit funktioniert das. Man kann auch die Daten aus der Datenbanktabelle in eine Tabelle laden und diese anzeigen.

    Wenn man jetzt aber noch die Zusatzfelder in der Datenbanktabelle ablegen will, ungefähr so:

    Table1->InsertRecord(ARRAYOFCONST((LfdNummer,
                                 DBStruktur.FeldA,
                                 DBStruktur.FeldA,
                                 (float)DBStruktur.Ergebnisse.Wert[0],
                                 (float)DBStruktur.Ergebnisse.Wert[1],
                                 (float)DBStruktur.Ergebnisse.Wert[2],
                                 (float)DBStruktur.Ergebnisse.Wert[3],
                                 (float)DBStruktur.Ergebnisse.Wert[4],
                                 (float)DBStruktur.Ergebnisse.Wert[5],
                                 (float)DBStruktur.Ergebnisse.Wert[6],
                                 (float)DBStruktur.Ergebnisse.Wert[7],
                                 (float)DBStruktur.Ergebnisse.Wert[8],
                                 (float)DBStruktur.Ergebnisse.Wert[9],
                                 (float)DBStruktur.Ergebnisse.Wert[10],
                                 (float)DBStruktur.Ergebnisse.Wert[11],
                                 (float)DBStruktur.Ergebnisse.Wert[12],
                                 (float)DBStruktur.Ergebnisse.Wert[13],
                                 (float)DBStruktur.Ergebnisse.Wert[14],
                                 (float)DBStruktur.Ergebnisse.Wert[15],
                                 DBStruktur.ZusatzA,       // <= 1. Zusatzfeld
                                 DBStruktur.ZusatzB,       // <= 2. Zusatzfeld
                                 DBStruktur.ZusatzC)));    // <= 3. Zusatzfeld
    

    dann wird beim Compilieren folgende Fehler-Meldung ausgegeben (und damit das Prog nicht erstellt):

    Compiler schrieb:

    **[C++Fehler] Unit7.cpp(183): Could not find a match for 'System::OpenArraySystem::TVarRec::OpenArray(int,System::AnsiString,System::AnsiString,float,float,float,float,
    float,float,float,float,float,float,float,float,float,float,float,float,System::AnsiString,System::AnsiString,System::AnsiString)'.

    [C++Fehler] Unit7.cpp(183): Could not find a match for 'System::OpenArrayCountSystem::TVarRec::OpenArrayCount(int,System::AnsiString,System::AnsiString,float,float,float,
    float,float,float,float,float,float,float,float,float,float,float,float,float,System::AnsiString,System::AnsiString,System::AnsiString)'.**

    Edit: Ich habe schon mit Name, Typ und Größe der Felder über die Datenbankoberfläche ein wenig herumexperimentiert, jedoch ohne Erfolg. 😞

    Könnt Ihr mir Tips geben? Oder weiß gar jemand recht genau, was diesen Fehler verursacht?



  • Hallo

    Vermutlich gibts es das Makro ARRAYOFCONST nur für eine gewisse Anzahl von Elementen, und die zusätzlichen Felder überschreiten diese Anzahl. Mit der DB hat das aber nichts zu tun, da würden erst zur Laufzeit Fehler kommen.
    Entweder suchst du dir eine andere Möglichkeit dieses Array zu erstellen, oder du verwendest gleich ein richtiges SQL-INSERT über ein TQuery. TTable ist jedenfalls immer eine schlechte Wahl.

    bis bald
    akari



  • Hello again akari,

    soll ich ehrlich sein? Ich hab' maximal die Hälfte verstanden! Wo könnte ich denn dieses Makro finden bzw. die Definition dazu? Die Idee hatte ich bereits das ARRAYOFCONST die Anzahl nicht zulässt, aber ich weiß nicht wo ich es finden kann, um es evtl. anzupassen... 😕



  • So, ARRAYOFCONST habe ich jetzt lt. Hilfe in der SYSDEFS.H gefunden. So siehts aus:

    // ARRAYOFCONST: construct an OpenArray<TVarRec> on the fly
    #define ARRAYOFCONST(values) \
      OpenArray<TVarRec>values, OpenArrayCount<TVarRec>values.GetHigh()
    

    Und was jetzt?



  • in der Hilfe zu ARRAYOFCONST steht ein Hinweis auf OPENARRAY und dort steht unter anderem folgendes

    BCB-Hilfe schrieb:

    OPENARRAY(T, (value1, value2, value3)) // Maximal 19 Werte

    d.h. du solltest dir eine andere Variante für das Füllen der Datenbank verwenden, z.B. TQuery und ein SQL-Kommando oder mit Hilfe der Methoden Append() und Post() von TTable

    wobei auch ich dir empfehlen würde (wenn möglich) die Komponenten der BDE (TTable, TQuery) aus dem Projekt zu nehmen und statdessen z.B. die ADO-Komponenten oder ähnliches zu verwenden



  • Das sagt die Hilfe:

    Borland C++Builder3 Hilfe schrieb:

    TVarRec wird in einer Prozedur mit dem Parametertyp array of const benutzt.

    Unit

    Sysdefs

    class TVarRec;

    typedef TVarRec* PVarRec;
    class TVarRec

    {
    public:
    union
    {
    Integer VInteger;
    Boolean VBoolean;
    Char VChar;
    PExtended VExtended;
    PShortString VString;
    Pointer VPointer;
    PChar VPChar;
    TObject* VObject;
    TClass VClass;
    WideChar VWideChar;
    PWideChar VPWideChar;
    Pointer VAnsiString;
    PCurrency VCurrency;
    PVariant VVariant;

    };
    union
    {

    Byte VType;
    long ForceAlignment;
    };

    Beschreibung

    Der Typ TVarRec wird in einer Prozedur mit dem Parametertyp array of const verwendet.
    Das Feld VType teilt der Prozedur den Typ jedes Parameters mit, der im offenen Array übergeben wird.
    Die Variablentypkonstanten repräsentieren die Werte, die im Tag der TVarRec-Struktur übergeben werden.
    Variablen dieses Typs können mit dem Makro ARRAYOFCONST erzeugt werden. Dieses Makro ist in der Datei SYSDEFS.H definiert.



  • Hmm... da war ich ja auf dem richtigen Weg... In meiner Hilfe steht zwar kein Hinweis auf OpenArray, aber nach OpenArray hätte ich als nächstes gesucht, wg der Zeile in Sysdefs.h.
    Meld mich gleich nochmal, wenn ich's gefunden und angepasst habe!

    Edit: Nagut, doch ein klitzekleiner Hinweis drin:

    Borland C++Builder3 Hilfe schrieb:

    Das Feld VType teilt der Prozedur den Typ jedes Parameters mit, der im offenen Array übergeben wird.

    🙄

    Edit2: Und in der Fehlermeldung steht ja auch ein Hinweis... *grummel*



  • Danke für Eure Tipps.
    da ich mich mit dem ganzen Datenbank-Zeugs nicht auskenne und eine schnelle Lösung gesucht habe, belasse ich es erstmal bei einer leicht modifizierten sysdefs.h ! Das scheint zu funktionieren.
    Den Datenbank-Kram hat, wie gesagt, ein Kollege gemacht und ich habe genug zu tun - also stricke ich den DB-Teil jetzt nicht um, zumal ich mit Datenbanken noch nie (!!!) etwas zu tun hatte. Wenn der Kollege nicht so... na sagen wir "eigensinnig" wäre, würde ich ihm doch glatt eure Vorschläge unterbreiten!

    Habt Ihr Einwände gegen das Modifizieren der sysdefs.h???



  • Ich würde nicht die "sysdef.h" verändern, sondern einfach das Makro in eine deiner Dateien umkopieren (und umbenennen) und dann auf mehr als 19 Parameter erweitern.

    Aber ihr scheint ja ein wirklich altes Projekt zu haben, wenn ihr noch den BCB 3 und die BDE benutzt...



  • Das geht natürlich auch, dann bleibt die sysdefs.h im Orginalzustand und es geht schnell; werd ich wohl morgen noch machen!

    Allerdings habe ich festgestellt, dass in der Tabelle, mit der man sich die Datenbank-Einträge anschauen kann, die Zusatzfelder immernoch leer sind. 😞
    Die Felder in der Struktur sind allerdings gefüllt...

    Nunja, BCB3 verwenden wir wegen der Portabilität - für BDS2006 haben wir nur X Lizenzen und am Projekt arbeiten aber X+N Kollegen. Irgendwie solch' einen Hintergrund hat das.



  • Hast du denn die Template-Methoden von OpenArrayCount richtig abgeändert, d.h. die Member-Variable "Count" richtig angepaßt (20, 21, 22, ...)?

    Aber es geht auch noch einfacher, ohne Änderung der sysdef.h und ohne Einbindung des Makros.

    const TVarRec Values[] =
    {
      LfdNummer, 
      DBStruktur.FeldA, 
      DBStruktur.FeldB, 
      (float)DBStruktur.Ergebnisse.Wert[0],
      ...
    };
    const int nCount = sizeof(Values)/sizeof(Values[0]);
    Table1->InsertRecord(Values, nCount-1); // Anzahl ist der Index des letzten Elements
    


  • __fastcall OpenArrayCount(T arg0, T arg1, T arg2, T arg3, T arg4, T arg5,
                      T arg6, T arg7, T arg8, T arg9, T arg10, T arg11, T arg12, T arg13,
    				  T arg14, T arg15, T arg16, T arg17, T arg18, T arg19, T arg20, T arg21): Count(22) {}
    

    Müsste so passen!?!



  • Ja, das müßte so passen, aber ich hatte meinen oberen Beitrag gerade noch editiert, damit es noch einfacher geht...



  • Also im Prinzip einfach ein eigenes OpenArray definieren?!



  • Tja, wie gesagt: Hab's wie oben - keine Compilermeldung, aber die Felder in der Tabelle sind leer. 😞


Anmelden zum Antworten