OK jetzt mal ganz kurz und knackig mein Problem mit ODBC



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



  • Der Debug stop bei: ASSERT(m_bTransactionPending);



  • Der ganze Abschnitt sieht so aus:

    BOOL CDatabase::CommitTrans()
    {
    	ASSERT_VALID(this);
    	ASSERT(m_hdbc != SQL_NULL_HDBC);
    
    	if (!m_bTransactions)
    		return FALSE;
    
    	// BeginTrans must be called first
    #ifdef _DEBUG
    	ASSERT(m_bTransactionPending);
    #endif
    
    	_AFX_DB_STATE* pDbState = _afxDbState;
    	RETCODE nRetCode;
    	AFX_SQL_SYNC(::SQLTransact(pDbState->m_henvAllConnections, m_hdbc, SQL_COMMIT));
    	BOOL bSuccess = Check(nRetCode);
    
    	// Turn back on auto commit
    	AFX_SQL_SYNC(::SQLSetConnectOption(m_hdbc, SQL_AUTOCOMMIT,
    		SQL_AUTOCOMMIT_ON));
    	DEBUG_ONLY(m_bTransactionPending = FALSE);
    
    	return bSuccess;
    }
    


  • Na, dann ist doch schon einfacher:

    // BeginTrans must be called first
    #ifdef _DEBUG
        ASSERT(m_bTransactionPending);
    #endif
    

    Was sagt dir der Kommentar? Hast du BeginTrans aufgerufen? 🙂



  • Hmmm Hups 🙄



  • Oh sch... SOOORRYY - das hab ich in meinem Beispiel total vergessen

    bitte nicht haun 😉



  • Ok da du mich hier ja so zusagen durch gebrügelt hast damit ich das verstehe und da ich nur noch eine Frage habe lass ich dich in ruhe und frag dich ganz lieb 😃



  • Falsche Antwort Tow-B 😃
    Du musst sagen, dass das volle Absicht war, wegen des Lerneffektes. 😉



  • Wieso speichert der Compiler :

    strSql = "Insert into tbl_Datenbank(Regal,Interpret, Titel, Rubrik, CD) values('NewSong.Shelf','NewSong.Interpreter','NewSong.Title','NewSong.Rubric','NewSong.CD')";
    

    Nicht den Inhalt von z.B. NewSong.Shelf sondern NewSong.Shelf an sich ab???
    Oder besser wie schaff ich es das er den Inhalt von NewSong.Shelf abspeichert??

    In NewSong.Shelf usw. stehen die eingetragenen Daten des Benutzers drin die dieser abspeichern will.



  • hehe 😉

    so un nu kommen wir dahin wo wir am anfang schon sein wollten 😉

    von welchem Typ ist NewSong.Shelf ?

    Ist das ein struct mit CStrings?
    in etwa so:

    struct song
    {
      CString Shelf;
      ...;
    };
    

    Alles was beim CString zwischen den "" steht ist ein String. Wenn du nun eine Variable dahineinfügen willst hast du mal wieder mehrere Möglichkeiten (ist das nicht schön? 🙂 )

    Am einfachsten isses wenn die Variablen auch CStrings sind, dann geht das ganz einfach mit dem +operator.

    CString strText1, strText2, strErgebnis;
    strErgebnis = "Hier kommt Text1:" + strText1 + " und hier Text2: " + strText2 + ". So das wars"
    

    Falls deine Variablen einen anderen Typ haben musst die Methode Format() des CStrings benutzen. Für ints zum Beispiel:

    int nZahl=0;
    CString strText;
    strText.Format("Zahl: %i", zahl);
    

    ob du wirklich richtig stehst..

    edit: das Semikolon ist für den Lerneffekt 😆



  • Um dir genau zu erklären was NewSong ist:

    MusicPiece NewSong;
    
    	NewSong.Interpreter = GetText( m_Interpreter );
    	//m_Interpreter.GetWindowText( temp );
    	//NewSong.Interpreter	= LPCTSTR( temp );
    
    	NewSong.Title = GetText( m_Title );
    
    	NewSong.Rubric = GetText( m_Rubric );
    
    	NewSong.Shelf = GetText( m_Shelf );
    
    	NewSong.CD = GetText( m_CD );
    

    MusikPiece ist diese Class:

    class MusicPiece  
    {
    public:
    
    	std::string Interpreter;
    	std::string Title;
    	std::string Rubric;
    	std::string CD;
    	std::string Shelf;
    
    public:
    	MusicPiece();
    	virtual ~MusicPiece();
    
    };
    
    typedef std::vector< MusicPiece > MusicPieceVector;
    

    💡 Also denke ich mal das ich mit format arbeiten muss 😃 (Lernreffekt) 👍

    Danke nochmals für deine Hilfe, du hast mir ganz schön weiter geholfen

    Hmm muss nur noch einen Fehler beheben dann sollte es funktionieren.

    Fehlermeldung:
    C:\Dokumente und Einstellungen\Dors\Desktop\C++ Projekte\Musik_Datenbank\MusicManagement.cpp(205) : error C2059: Syntaxfehler : ';'

    Hmm mal sehen was das sein könnte 😕

    Gruss Silver



  • Hi nochmal,
    ich bin mal so frei und zitiere mich mal eben selber, hatte das nämlich vor ca 10 Postings schon geahnt 🙂

    Tow-B.de schrieb:

    benutz mal CString und nicht std::string

    Wenn du den std::string behalten willst geht das glaub ich mit:

    CString text;
    std:string wert;
    text.Format("%s", wert);
    

    Habe das jetzt aber selber noch nicht getestet 🙂



  • Hi
    ich habe mittlerweile ne andere Lösung gefunden: 😃

    void MusicManagement ::StoreDB(MusicPiece NewSong)
    {
    	CDatabase music_data;
    	CString SqlString;
    	CString strErgebnis;
    
    		// Open the database
    		music_data.Open( "MUSIK" );
    
    		music_data.BeginTrans();
    		SqlString.Format( "%s,%s,%s,%s,%s", NewSong.Shelf.c_str(),NewSong.Interpreter.c_str(),NewSong.Title.c_str(),NewSong.Rubric.c_str(),NewSong.CD.c_str());
    		strErgebnis = "Insert into tbl_Datenbank";
    		strErgebnis += (LPCTSTR)SqlString;
    		music_data.ExecuteSQL(strErgebnis); // SQL absenden
    		music_data.CommitTrans(); // daten festschreiben
    
    		music_data.Close();
    
    }
    

    Jetzt gibt der mir keinen Fehler mehr aus, sagt mir aber wenn ich auf den Speicherbutton drück : " Syntaxfehler in der INSERT INTO - Anweisung ".

    Da häng ich zur Zeit fest, ich kann mit der Fehlermeldung nichts anfangen.

    HINWEIS: Die Fehlermeldung kommt aks MessageBox der Compiler sagt das alles in Ordnung ist. 😕



  • Der Feher kommt von der Datenbank, irgendwie baust du den "Insert-Befehl" falsch zusammen.

    Lass dir mal strErgebnis ausgeben bevor du es an die Datenbank schickst

    hierman kannst du dann das Ergebnis direkt ausm Debugger kopieren:

    TRACE(strErgebnis);
    

    Wenn du WindowsXP hast kannst du auch einfach ne MessageBox nehmen, wenn der Fehler da ist STRG+C drücken und schon hat man den Text der MsgBox im Speicher und kann ihn irgendwo einfügen 😉

    Es msste bei dir in etwa so aussehen (denke ich):

    SqlString.Format( "'%s','%s','%s','%s','%s'", NewSong.Shelf.c_str(),NewSong.Interpreter.c_str(),NewSong.Title.c_str(),NewSong.Rubric.c_str(),NewSong.CD.c_str());
            strErgebnis = "Insert into tbl_Datenbank(spalte1, spalte2, spalte3, spalte4, spalte5) values ";
    

    und die Worte "spalte1" bis "spalte5" ersetzt du durch deine Spaltennamen! Damit sollte es dann klappen..

    Wenn nicht, schick mal den SQL, also genau das was du an die Datenbank schickst (direkt vor dem ExecuteSQL).



  • oder probier mal, den tabellennamen in eckige klammern zu setzen. ansonsten lassen sich solche sql-befehle auch ganz gut in access testen, da wird nämlich angezeigt, wo genau der fehler ist



  • ja genau, einfach ne Abfrage erstellen und dann in die SQL-Ansicht gehen, da kannste die SQLs testen..



  • Hallo also es klappt immer noch nicht:

    void MusicManagement ::StoreDB(MusicPiece NewSong)
    {
    	CDatabase music_data;
    	CString SqlString;
    	CString strErgebnis;
    
    		// Open the database
    		music_data.Open( "MUSIK" );
    
    		music_data.BeginTrans();
    		SqlString.Format( "%s,%s,%s,%s,%s", NewSong.Shelf.c_str(),NewSong.Interpreter.c_str(),NewSong.Title.c_str(),NewSong.Rubric.c_str(),NewSong.CD.c_str());
    		strErgebnis = "Insert into tbl_Datenbank(Regal,Interpret,Titel,Rubrik,CD) values ";
    		strErgebnis += (LPCTSTR)SqlString;
    		music_data.ExecuteSQL(strErgebnis); // SQL absenden
    		music_data.CommitTrans(); // daten festschreiben
    
      strErgebnis = "Insert into tbl_Datenbank(spalte1, spalte2, spalte3, spalte4, spalte5) values ";
    		music_data.Close();
    
    }
    

    Hier jetzt mal die komplette Methode das mit den Klammern um die tabelle hab ich auch probiert, klappt ebenfalls nicht.

    Was ich noch nicht so ganz verstanden habe ist der Tip mit der Abfrage erstellen, soll ich einfach ne Abfrage in Access machen? Und dann seh ich ob das funktioniert ???

    Wenn ich das Trace ausprobiere hat strErgebnis alle Werte übernommen drücke ich auf F10 geht der in einen anderen Bereich und zeigt hier einen Fehler und geht nicht weiter:

    [cpp]// special case for WM_INITDIALOG
    		CRect rectOld;
    		DWORD dwStyle = 0;
    		if (nMsg == WM_INITDIALOG)
    			_AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
    
    		// delegate to object's WindowProc
    		lResult = pWnd->WindowProc(nMsg, wParam, lParam);
    
    		// more special case for WM_INITDIALOG
    		if (nMsg == WM_INITDIALOG)
    			_AfxPostInitDialog(pWnd, rectOld, dwStyle);
    	}
    	CATCH_ALL(e)
    	{
    		[b]lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);[/b] //genau hier bleibt der Compiler hängen
    		TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
    			lResult);
    		DELETE_EXCEPTION(e);
    	}
    	END_CATCH_ALL
    
    	pThreadState->m_lastSentMsg = oldState;
    	return lResult;
    }[/cpp]
    


  • Ja, das ist schon ganz gut soweit..

    Zum ersten: Ja, einfach irgeneine Abfrage in Access erstellen, und dann in die Entwurfsansicht, und dann auf SQL umstellen.
    Jetzt kannst du den kompletten Insert aus dem TRACE rauskopieren und in die Abfrage einfügen. Abfrage speichern, und per doppelklick ausführen.

    Jetzt sollte ein Fehler kommen der sagt wo der Fehler in dem SQL-Statement ist. Den brauchen wir 😉

    Den Fehler kann man natürlich auch vom Programm aus holen und dann anzeigen lassen, dazu benötigt man dann Exception-Handling (Try/Catch/CDBException).



  • Du hast einfach die Klammern um die Werte vergessen:

    SqlString.Format( "(%s,%s,%s,%s,%s)", NewSong.Shelf.c_str(),NewSong.Interpreter.c_str(),NewSong.Title.c_str(),NewSong.Rubric.c_str(),NewSong.CD.c_str());
    


  • und die einfachen Anführungszeichen:

    SqlString.Format( "('%s','%s','%s','%s','%s')", NewSong.Shelf.c_str(),NewSong.Interpreter.c_str(),NewSong.Title.c_str(),NewSong.Rubric.c_str(),NewSong.CD.c_str());
    

    weil es strings sind. ich glaube Access benötigt die auch..


Anmelden zum Antworten