Code Verständnisproblem



  • Ja ich habe eine kleine Access Datenbank . Ich speicher hier:

    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 "; //conection with the databse
    		strErgebnis += (LPCTSTR)SqlString;
    		strErgebnis.Replace("''","NULL");
    		music_data.ExecuteSQL(strErgebnis); // send to database
    		music_data.CommitTrans(); // stor data
    
    		music_data.Close();
    
    }
    

    Den Code müsstest du eigentlich noch kennen 🙂



  • Ja, da war was... 😃

    Aber ich wollte doch gar nicht den Code für das Speichern. Ich möchte den, wo du das Listcontrol füllst. Wo liest du aus der Datenbank?

    Weitere Frage: Hat deine Tabelle keinen Primärschlüssel? Woran identifizierst du denn die Datensätze eindeutig? Denn, du musst ja rausfinden, welche genau du löschen willst.



  • Achso Sorry 🙄 Hab das falsch verstanden.

    Hier lese ich aus der Datenbank:

    void MusicManagement::ReadDB()
    {
    
    	CDatabase Musik_Daten;
    	CString DB_File = "MUSIK";
    	CString sDsn;
    	CString sDriver = "MICROSOFT ACCESS DRIVER (*.mdb)";
    	CString SqlString;
    
    	// The ODBC Connection String
    
    	sDsn.Format("ODBC;DRIVER={%s};DSN='MUSIK';DBQ=%s",sDriver,DB_File);
    
    	TRY
    	{
    		// Open the database
    		Musik_Daten.Open( "MUSIK" );
    
    		// Allocate the recordset
    		CRecordset recset( &Musik_Daten );
    
    		// Build the SQL statement
    		SqlString =  "SELECT Regal, Interpret, Titel, Rubrik, CD "
    				"FROM tbl_Datenbank";
    
    		// Execute the query
    		recset.Open(CRecordset::forwardOnly,SqlString,CRecordset::readOnly);
    
    		// Loop through each record
    		CString Shelf;
    		CString Interpreter;
    		CString Title;
    		CString Rubric;
    		CString CD;
    
    		while( !recset.IsEOF() )	
    		{
    			// Copy each column into a variable
    			recset.GetFieldValue("Regal",Shelf);
    			recset.GetFieldValue("Interpret",Interpreter);
    			recset.GetFieldValue("Titel",Title);
    			recset.GetFieldValue("Rubrik",Rubric);
    			recset.GetFieldValue("CD",CD);
    
    			MusicPiece music;
    
    			music.Shelf		  = Shelf;
    			music.Interpreter = Interpreter;
    			music.Title		  = Title;
    			music.Rubric	  = Rubric;
    			music.CD		  = CD;
    
    			m_MusicCollection.MusicData.push_back( music );
    
    			// go to next record
    			recset.MoveNext();
    		}
    
    		// Close the database
    		Musik_Daten.Close();
    
    	}
    	CATCH(CDBException, e)
    	{
    			// If a database exception occured, show error msg
    			AfxMessageBox("Database error: "+e->m_strError);
    	}
    
    	END_CATCH;
    
    	}
    

    Und natürlich habe ich einen Primärschlüssel , der wird doch automatisch gesetzt. Momentan identifiziere ich die nirgendswo



  • Dann lade den mal mit, den brauchst du für das Löschen. 🙂

    Und dann zeig bitte noch die Stelle, wo du die geladenen Daten für die Anzeige ins Listcontrol packst.
    Denn da musst du mit SetItemData den Autowert an jede Zeile anhängen, damit du ihn beim Löschen abfragen kannst.



  • Hier ist der Code:

    for ( ; it != itend; ++it )
    		{
    			MusicPiece& music = *it; 
    
    			TRACE( "%s\r\n", music.Interpreter.c_str() );
    
    			int item = m_ListDataFound.InsertItem(0,0,0);
    			m_ListDataFound.SetItem( item , 0 , LVIF_TEXT, music.Shelf.c_str(), 100 , 0 , 0 , 0 );
    			m_ListDataFound.SetItem( item , 1, LVIF_TEXT , music.Interpreter.c_str(), 100 , 0 , 0 , 0 );
    			m_ListDataFound.SetItem( item , 2 , LVIF_TEXT , music.Title.c_str(), 100 , 0 , 0 , 0  );
    			m_ListDataFound.SetItem( item , 3 , LVIF_TEXT , music.Rubric.c_str(),100 , 0 , 0 , 0 );
    			m_ListDataFound.SetItem( item , 4 , LVIF_TEXT , music.CD.c_str(),100 , 0 , 0 , 0 );
    
    		}
    

    Dann soll ich also auch die ID mit anzeigen lassen also überall ID hinzufügen??



  • Dann soll ich also auch die ID mit anzeigen lassen also überall ID hinzufügen??

    Wie genau liest du eigentlich, was ich so schreibe? 🙄

    Denn da musst du mit SetItemData den Autowert an jede Zeile anhängen, damit du ihn beim Löschen abfragen kannst.
    

    Du musst die Zahl nicht anzeigen, das sähe ja doof aus. 😉

    Das hier meinte ich:

    m_ListDataFound.SetItemData( item , music.ID );
    


  • Wie genau liest du eigentlich, was ich so schreibe?

    Genauso wie jeder andere auch

    Du musst die Zahl nicht anzeigen, das sähe ja doof aus. 😉

    OK hast recht

    Das hier meinte ich:

    estartu_de schrieb:

    p]m_ListDataFound.SetItemData( item , music.ID );

    das meinte ich dann muss ich jetzt überall erstmal nen ID hinzufügen.



  • OK erledigt ID ist hinzugefügt



  • Was ich jetzt noch nicht so ganz verstehe was habe ich davon wenn jeder Datensatz weiss was für ne ID er hat, aber ich später bei m_ListDataFound.DeleteItem(nItem) doch diese ID gar nicht nutzen kann??



  • Doch, kannst du.
    Du musst ja jede Zeile zweimal löschen.

    Einmal im Control - das tust du schon.
    Und dann noch in der Datenbank, das musst du noch einbauen.

    Dazu brauchst du dann das ItemData von dem markierten Eintrag, damit du das where basteln kannst.



  • Ich bastel mal zusammen, wie ich das meine:

    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.Format("Delete from [tbl_Datenbank] where [ID] = %d", m_ListDataFound.GetItemData( item )); //conection with the databse
            music_data.ExecuteSQL(strErgebnis); // send to database
    

    Das packst du VOR das Löschen aus dem Listcontrol, aber in die Schleife.
    Variablendeklaration musst du noch machen, aber die solltest du ja kennen. 😉



  • Und dieses ItemData befinden sich in nItem



  • Unsere Posts haben sich wohl überschnitten, guck mal oben. 🙂



  • Achso du nutz einen Delete Befehl



  • Was anderes würde mir ehrlich gesagt bei deiner Auslesemethode nicht einfallen.

    Würdest du statisch und nicht dynamisch zugreifen, gäbe es noch eine andere Möglichkeit.
    Ahja, du kannst das delete noch optimieren, indem du mit ... [ID] in (...) arbeitest. Dann wird das nur einmal ausgeführt und nicht für jede Zeile, aber das ist nur noch Kür. 😉



  • OK danke guck mal ob ich das jetzt hinbekomm 😃 Wenn nicht dann muss ich mir überlegen ob ich nicht lieber was anderes lernen will ausser Prog 🙄



  • Nanana, so schlimm ist es doch nun auch nicht. 😉
    Du hast dich ja auch gleich an die Aufgaben für Fortgeschrittene gewagt - die sind schwerer, aber du lernst mehr. 🙂



  • Wenn du das sagst



  • Eine Frage hätte ich aber noch ich hab den Code zwar jetzt angepasst, aber ich weiss noch nicht so recht wie ich DeleteSong mit den Daten aus der List fülle:

    CDatabase music_data;
    	CString SqlString;
    	CString strErgebnis;
    
    	MusicPiece DeleteSong;
    
    	    // Ist was markiert?
            POSITION pos = m_ListDataFound.GetFirstSelectedItemPosition();
            if (pos == NULL)
            { // Nichts gewählt, Fehlermeldung oder nix machen
    			MessageBox("Es wurde kein Eintrag zum Löschen ausgewählt","Fehler",MB_OK);
            }
            else
            {
                while (pos)
                {
    
    				 SqlString.Format( "('%s','%s','%s','%s','%s')", DeleteSong.Shelf.c_str(),DeleteSong.Interpreter.c_str(),DeleteSong.Title.c_str(),DeleteSong.Rubric.c_str(),DeleteSong.CD.c_str());
    				strErgebnis.Format("Delete from [tbl_Datenbank] where [ID] = %d", m_ListDataFound.GetItemData(???)); //conection with the databse
    				 music_data.ExecuteSQL(strErgebnis); // send to database
                    // Index des Items holen und gleich weitersetzen
                    int nItem = m_ListDataFound.GetNextSelectedItem(pos);
                    // nItem ist der Index des Eintrags
    				m_ListDataFound.DeleteItem(nItem);
    
                }
            }
    

    Bis jetzt habe ich ja immer nur die m_Variablen kopiert, aber wie kann ich auch den Inhalt der list zugreifen?? Muss ich da etwa pos als so ne art Zähler benutzen?? Also DeleteSong[pos].Shelf ?? Oder wie mach ich das??
    Und mein Zweites problem in dem Code ist hinter GetItemData nen Fragezeichen, weil ich nicht weiss was ich da reinschreiben soll wenn ich pos reinschreib dann funktioniert das nicht dann sagt er logischerweise das er kein int konvertieren kann

    Gruss Silver



  • ??? muss nItem sein.
    Und MusicPiece brauchst du an der Stelle nicht, da du dir die ID ja extra gemerkt hast. 🙂

    Und die erste Zeile in der Schleife (SqlString.Format...) kannst du löschen.

    Hast du nun verstanden, was ItemData ist und wie es mit der ID aus der Datenbank zusammenhängt?


Anmelden zum Antworten