OK jetzt mal ganz kurz und knackig mein Problem mit ODBC



  • Hallo
    da irgendwie niemand so recht meinen Fehler versteht siehe ODBC Driver Problem,
    werde ich nun mal versuchen mein Problem haar genau auf den Punkt zu bringen hoffe man kann mir dann endlich weiter helfen.

    Was hab ich:

    Eine Musik Datenbank die :

    -Lieder suchen kann
    -Lieder aus ner Datenbank laden kann
    -Lieder sortieren kann auf und abwärts

    Was kann sie nicht:
    -Lieder in eine Datenbank speichern

    Und wieso nicht?

    -Weil ich nicht weiss wie ich an die Variablen aus der Datenbank komme um in diese Variablen die neuen Daten abzuspeichern

    CRecordSet::AddNew();
    
    // Hier müssten jetzt die Daten die eingegeben werden in die Datenbank Variablen gespeichert werden (Aber wie kann ich auf die Datenbank Variablen zugreifen??)
    
    CRecordSet::Update();
    CRecordSet::Requery();
    

    versteht jemand mein Problem und kann mir helfen???

    Langsam verzweifel ich. Um es nochmals zu verdeutlichen kleiner Codeausschnitt aus einem Beispiel:

    http://www.se.fh-heilbronn.de/usefulstuff/VCPLUS6/kap14.htm

    In diesem Beispiel werdet Ihr unter der Tabelle 14.5 auf diese Zeilen stoßen.

    m_pSet scheint eine Member - Variable zu sein die Zugriff auf die dort genutzte Datenbank hat. Diese Member - Variable kann auf die Datenbankvariablen zugreifen und Sie dadurch mit dem Inhalt der MFC Variablen füllen.
    Wie bekomme ich so eine Member - Variable (m_pSet)

    // Einen neuen Datensatz in den Recordset einfügen
    m_pSet.AddNew();
    // Das Schlüsselfeld auf den neuen Datensatz setzen
    [b]m_pSet.m_AddressID[/b] = m_lNewID;
    // Den neuen Datensatz in der Datenbank speichern
    m_pSet.Update();
    // Den Recordset aktualisieren
    m_pSet.Requery();
    // Zum neuen Datensatz gehen
    m_pSet.MoveLast();
    

    gruss Silver



  • also, normalerweise bekommt man eine solche membervariable, in dem man die entsprechende datenbank einbindet. in diesem fall gibt es eine klasse ...Set in der die einzelnen Membervariablen hinterlegt sind.
    das geht meines wissens automatisch. Ansonsten:
    in der ...Doc eine variable mit dem Namen m_pHandleSet (bspw) anlegen als Instanz der ...Set.
    Die variable m_pSet ist in der klasse ...View dann eine Instanz der klasse ...Set und müsste in der ...View.h angelegt und in der ...View in der Funktion OnInitialUpdate() folgendermassen referenziert werden: m_pSet = &GetDocument()->m_pHandleSet.
    damit müsste man dann aus ...View auf m_pSet->Variable zugreifen können.



  • Was meinst du als mit deinen ...SET und ... View?? Meinst du damit Record??



  • So, dann jetzt nochmal langsam 😉 Im anderen Thread war leider was ich gesagt hatte nicht ganz korrekt. Im Prinzip schon, nur habe ich verdrängt gehabt das es ja gar kein SetValue() gibt 😃
    Ich habe eben nochmal ne Test-Anwendung erstellt und da ist mir auch gleich der Fehler aufgefallen 🙂

    Wenn du das mit AddNew machen möchtest, musst du erstmal eine eigene Klasse von CRecordSet ableiten - darin kannst du dann Membervariablen für jede Spalte anlegen und die virtuelle Funktion DoDataExchance(CFieldExchange *pFX) überschreiben. Darin verbindet man dann die Tabellenspalten mit den Membervariablen 🙂

    void CAddNewTestSet::DoFieldExchange(CFieldExchange* pFX)
    {
    	pFX->SetFieldType(CFieldExchange::outputColumn);
    // Makros, z.B. RFX_Text() und RFX_Int(), sind vom Typ
    // der Membervariablen abhängig, nicht vom Typ des Felds in der Datenbank.
    // ODBC konvertiert den Spaltenwert automatisch in den angeforderten Typ.
    	RFX_Long(pFX, _T("[ID]"), m_ID);
    	RFX_Text(pFX, _T("[Spalte1]"), m_Spalte1);
    	RFX_Text(pFX, _T("[Spalte2]"), m_Spalte2);
    	RFX_Text(pFX, _T("[Spalte3]"), m_Spalte3);
    
    }
    

    Dann benutzt man für den Zugriff auf die Tabelle einfach nur noch die eigene abgeleitet Klasse, die Werte die in die Tabellen sollen, weist man dann den Membervariablen zu 🙂

    Ich würde dir Empfehlen: Erstell einfach mal ne neue Anwendung (SDI) mit Datenbankunterstützung. Dann wählst du den Access-Treiber aus, und wählst danach deine Datenbank und die Tabelle darin aus.
    Wenn der Assistent dir nun alles erstellt hat, kannst du dir ansehen was du alles brauchst.
    Evtl. ist es aber sogar einfach in die neue Anwendung dann die Resourcen und den Code der "alten" Anwendung zu kopieren.
    --------------------------
    Wenn du es am einfachsten haben willst, schreib nen Insert und schick den in deiner jetzigen anwendung einfach an dein Datenbankobjekt.

    CDatabase db; // DB-Objekt erzeugen
    db.open(.....); // DB öffnen
    strSQL = "Insert into tabelle(Spalte1, Spalte2, Spalte3) values('"+strSpalte1+"','"+strSpalte2+"','"+strSpalte3+"'"; //SQL schreiben
    db.ExecuteSQL(strSQL); // SQL absenden
    db.committrans(); // daten festschreiben
    

    So mach ich es immer, beim updaten dann genauso - vor allem wenn man viele Tabellen hat ist es imho viel praktischer 😉



  • also, ich bin davon ausgegangen, dass du ein projekt angelegt hast und deine datenbanktabellen darin eingebunden hast, indem du für jede tabelle eine klasse von crecordset abgeleitet hast. die ... stehen dann für den projektnamen. und der rest funktioniert dann automatisch



  • @daniel12345: Es gibt noch einen zweiten Thread zu dem Thema.. 🙂



  • Genau das meinte ich Tow-B.de, ich hatte in deiner anderen antwort nicht das gefühl als hättest du verstanden was ich wollte, deswegen hab ich das ja nochmals so ausführlich geschrieben. Danke für deine Hilfe



  • Hallo Tow-B.de du hattest mir ja die beschreibung zum speichern in dateien gegeben, ich dachte auch das ich es ENDLICH verstanden hätte nur wenn ich:

    strSQL = "Insert into tabelle(Spalte1, Spalte2, Spalte3) values('"+strSpalte1+"','"+strSpalte2+"','"+strSpalte3+"'"; //SQL schreiben
    

    in diese Spalte meine Spaltennamen eintrage, sagt mir der Compiler als das ich ein Semikolon vor jeder Spalte vergessen hätte 😕 das verwirrt mich etwas.

    Des weiteren ich mus doch strSQL als CString festlegen oder??

    gruss Silver



  • Versuch mal:

    strSQL = "Insert into tabelle(Spalte1, Spalte2, Spalte3) values(\'"+strSpalte1+"\',\'"+strSpalte2+"\',\'"+strSpalte3+"\'"; //SQL schreiben
    


  • Hi,

    klar, strSQL musst du als CString deklarieren, auch strSpalte1, strSpalte2 und strSpalte3 sind CStrings! Ich denke mal das du nicht immer das selbe in die Spalten schreiben willst, oder? ansonsten:

    trSQL = "Insert into tabelle(Spalte1, Spalte2, Spalte3) values('test','test','test')";
    

    Die Tabellenspalten sollten dabei aber vom Typ Text sein.

    Aber was für ein Problem hast du mit Semikolons(li,la? 😃 ) Hast du mal nen genaueren Fehler? Bzw wo kommt der Fehler? Beim ausführen, oder beim compilieren?

    Ach du schreibst übrigens in eine Datenbank, okay bei Access entspricht die Datenbank einer Datei, das muss aber nicht immer so sein.

    edit: Bei dem obigen SQL fehlt einfach nur die letzte Klammer 😉

    (schon zweimal edited, sekt zum mittag kommt ned so gut 😃 )

    edit3: du musst vor den single-quotes nicht escapen, mach ich auch nie. Allerdings habe ich so das Gefühl das er die Variablen nach values auch durch seine Spaltennamen ersetzt hat.



  • Die Fehlermeldung ist immer noch da 😕

    Das sind die Fehlermeldungen:

    C:\Dokumente und Einstellungen\Dors\Desktop\C++ Projekte\Musik_Datenbank\MusicManagement.cpp(216) : error C2146: Syntaxfehler : Fehlendes ';' vor Bezeichner 'NewSong'

    C:\Dokumente und Einstellungen\Dors\Desktop\C++ Projekte\Musik_Datenbank\MusicManagement.cpp(216) : error C2143: Syntaxfehler : Fehlendes ';' vor 'string'

    ausserdem noch

    C:\Dokumente und Einstellungen\Dors\Desktop\C++ Projekte\Musik_Datenbank\MusicManagement.cpp(216) : error C2679: Binaerer Operator '=' : Kein Operator definiert, der einen rechtsseitigen Operator vom Typ 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' akzeptiert (oder keine geeignete Konvertierung moeglich)

    Hmm 😕



  • benutz mal CString und nicht std::string



  • Hatte das schon richtig gemacht, musste das nur so um ändern wie du es in deinem letzten Beispiel geschrieben hattest:

    trSQL = "Insert into tabelle(Spalte1, Spalte2, Spalte3) values('test','test','test')";

    Wobei ich aber weiterhin nen CString strSQL benutzen kann.

    Nur da wo du Insert into tabelle schreibst, muss ich da net einfach meinen Tabellennamen aus Access angeben????



  • Der Compiler sagt mir nämlich als Ausgabetabelle nicht gefunden, wenn ich schreibe Insert into tblDatenbank(......)



  • klar muss da dein tabellenname rein 🙂

    ich merke schon, du lernst schon noch SQL. Das solltest du dir mal genauer ansehen. Dann kannst du deine ganzen Infos deiner Sammlung in Tabellen speichern und einfach nen Select drauf loslassen und brauchst das Ergebnis nur noch anzeigen lassen - sogar schon sortiert 😉

    http://www.sql-und-xml.de/sql-tutorial/insert-zum-einfuegen-von-zeilen.html



  • Ich hab von SQL keine ahnung, hab nur mit Access zu tun gehabt. Und dort war das einzige wirkliche was mit SQL richtig zu tun hatte abfragen erstellen.
    Aber wieso sagt mir der Compiler das er meine Datenbanktabelle nicht finden kann??



  • Ok Fehler gefunden jetzt bekomme ich aber wenn ich abspeichern will ne komische Meldung:

    Debug Assertion Failed
    Dann nennt der den Pfad meiner Datenbank
    Dann kommt File: dbcore.cpp
    line:512

    Was heisst das??



  • Drück "Wiederholen", zeig den Code, wo du landest.
    (Achte besonders auf Kommentare und die Zeichenfolge Assert.)



  • HILFE!!!!!!!! 😮

    Jetzt bin ich total verwirrt ich krieg eine Fehlermeldung nach der anderen.

    z.B. Unbehandelte Ausnahme bei 0x5f7023e3 (MFCD42D.DLL) in Musik_Datenbank.exe: Benutzerhaltepunkt.

    oder : Eine Ausnahme "Unbehandelte Win32 - Ausnahme"ist in Musik_Daten.exe aufgetreten

    Was nun????



  • Startest du mit F5? Siehst du irgendwelchen Quellcode, wo das Wort AssertIsWindow oder ASSERT oder so vorkommt?


Anmelden zum Antworten