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 20Soweit 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. Zusatzfelddann 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.
