Autor Beitrag
.c0dy
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Di 23.04.13 14:46 
Hey Leute :)

Ich hab mich nun einfach mal hier registriert um an Hilfe zu kommen :)

Ich hab mich mitlerweile Dumm und Dümmer gesucht.

Kurz und knapp zu mir.

Ich habe vor ca. 4 Jahren für 2 Jahre in der Schule mit C# programmiert. Hatte dann allerdings weder privat noch beruflich damit zu tun gehabt.
Nun kommt es aber wieder auf mich zu. Ich bin zwar kein kompletter Anfänger, stelle mich aber aufgrund der längeren Pause ein wenig wie einer an :D

Es geht um folgendes.

Ich entwickle ein C#-Programm mit welchem ich eine Datenbank abfragen will.
Ich habe diverse Comboboxen.

Z.B. Kostenstelle und Standort.

Ich lasse beim Programmstart direkt alle Kostenstellen in die Combobox eintragen. Klappt auch wunderbar. (Dazu gäbe es noch einen Schönheitsfehler, wo mir evtl auch weitergeholfen werden kann. Ist aber nicht das wichtigste.) Die Kostenstellen sind mit Absicht mit z.B. "0002" in der Datenbank eingetragen. In der Combobox erscheint allerdings nur die "2". Das ist wie gesagt nur ein "Schönheitsfehler".

Jetzt zu dem Problem.


Befüllen der Combobox "Kostenstelle" funktioniert. Pro Kostenstelle ist in der Datenbank auch gleich der Standort hinterlegt.

Demnach soll beim ändern der Kostenstelle gleich der Standort mit angepasst werden.

Mein Code sieht folgender Maßen aus.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
void ProgrammLoad(object sender, EventArgs e)
        {
          
        
        // Aufbau der Verbindung zur Datenbank
      using (MySqlConnection conKST = new MySqlConnection(dbconnect
          ))
        {
          conKST.Open();
          // Erstellen eines neuen DataAdapter
          using (MySqlDataAdapter daKST = new MySqlDataAdapter(
          "SELECT Kostenstelle FROM Inventar", conKST))
          {
            // Verwendung des DataAdapter um DataTable zu befüllen
            DataTable datKST = new DataTable();
            daKST.Fill(datKST);
            // Daten auf den Bildschirm rendern
            cbKostenstelle.DataSource = datKST;
          }
          conKST.Close();
            }
        
          using (MySqlConnection conSO = new MySqlConnection(dbconnect
          ))
        {
              
          string cmdStandort = ("SELECT Standort FROM Inventar WHERE Kostenstelle = 0002");
          MySqlCommand cmdSO = new MySqlCommand (cmdStandort, conSO);
          
          //cmdSO.Parameters.AddWithValue("Kostenstelle", SqlDbType.Int).Value = "Kostenstelle";
          //cmdSO.Parameters.AddWithValue("Kostenstelle", cbKostenstelle.SelectedItem);
          
          conSO.Open();
          using (MySqlDataAdapter daSO = new MySqlDataAdapter(cmdStandort, conSO))
          {
            // Verwendung des DataAdapter um DataTable zu befüllen
            DataTable datSO = new DataTable();
            daSO.Fill(datSO);
            // Daten auf den Bildschirm rendern
            cbStandort.DataSource = datSO;
          }
          
          conSO.Close();
            }



Ich habe in der Standortabfrage jetzt selber "0002" eingetragen. Das entsprechende Ergebnis ist auch das richtige. Jedoch wird die Combobox nicht mit allen Möglichkeiten der Standorte befüllt.

Vielleicht könnt ihr mir ja helfen :)

Ich würde mich sehr freuen :)

Mit freundlichen Grüßen

.c0dy
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 23.04.13 17:07 
Hallo .c0dy :welcome:

codetechnisch sieht alles in Ordnung bei dir aus, daher kann ich dir keine konkreten Tipps geben.
Von welchem Datenbank-Datentyp ist denn die Spalte "Kostenstelle"? Laut deinem auskommentierten Code ja vom Typ 'Int', d.h. es gibt keinen Unterschied, ob man 0002, 002, 02 oder 2 schreibt.

Und was genau meinst du denn mit
.c0dy hat folgendes geschrieben:
Das entsprechende Ergebnis ist auch das richtige. Jedoch wird die Combobox nicht mit allen Möglichkeiten der Standorte befüllt.
?
Die Inhalte in der DataTable sind richtig, aber in der ComboBox nicht?

Für diesen Beitrag haben gedankt: .c0dy
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Di 23.04.13 19:49 
damit meinte ich, dass ich testweise hardcoded die Kostenstelle eingegeben habe. Wie im Beispiel oben.


Der richtige Wert wird dann aus der Datenbank ausgelesen.

Allerdings klappt es nicht so, dass ich die Kostenstelle variable aus der entsprechenden Combobox in die SQL-Abfrage "einspiele, sodass jeh nach Auswahl aus der Box auch gleich der Standort angepasst wird.


der typ ist, wenn ich das richtig im Kopf habe (schreibe gerade vom Handy), Int mit Zerofill und eben auf 4 stellen begrenzt.


und die Combobox "Standort" wird mit gar keinen Daten gefüllt. Obwohl ich jetzt gerade beim schreiben glaube ich das Problem gelöst habe.


Ich fülle die Box ja nur mit dem Wert bezogen auf die Kostenstelle. nicht allgemein. Ich werde später nochmal am pc testen :)



Danke aber schonmal :)
san-software
Hält's aus hier
Beiträge: 11
Erhaltene Danke: 3



BeitragVerfasst: Mi 24.04.13 13:31 
Also erst mal zum "Schönheitsfehler".
Bei Kontoangabe, wie es in der Buchhaltung üblich ist, verwendet man für die Kontonummer überlichweise kein Zahlenfeld, sondern ein Textfeld, in Deinem fall mit in einer Zeichenanzahl von 4 (VARCHAR(4) in der DB). Dann bleiben auch die führenden Nullen. Bei Zahlen werden die nämlich generell entfernt.

Die Sache mit dem Standort ist so, daß Du hier ja eine Combobox befüllst.
Eine Combobox besteht aus zwei Teilen:
1. Eine Listbox, die mit den werten befüllt wird, die zur Auswahl stehen.
2. Eine Textbox, in die der ausgewählte Wert eingetragen wird.

Was du hier tust, ist nichts anderes, als die Listbox mit Standort(en?) zu füllen, die bei Konto 0002 hinterlegt sind.
Ich finde jedoch keinen Code, mit dem Du etwas in die Textbox schreibst.

Du hast da meiner Meinung einen Denkfehler.
Ich gehe mal davon aus, daß zu jedem Konto ein (und nur ein) Standort zugeordnet ist bzw. wird.
Dann wäre der richtige Weg, die Listbox auch beim Programmstart mit allen möglichen Standorten zu beladen (wie beim Konto auch)
Beim Auswählen des Kontos mußt du dann nur den Standort des Kontos einlesen, wie Du es ja schon machst.
Und Diesen Standort mußt Du dann in die Textbox schreiben.

Für diesen Beitrag haben gedankt: .c0dy
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Mi 24.04.13 15:09 
Danke für die Antwort :)

Den ersten Denkfehler hatte ich ja schon gesehen.
Jeder Kostenstelle ist nur exakt ein Standort zugewiesen, richtig.

Ursprünglich war meine Idee zu sagen, dass der Standort von der ausgewählten Kostenstelle genommen wird.


Anfangs war der Code:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
string cmdStandort = ("SELECT Standort FROM Inventar WHERE Kostenstelle = @Kostenstelle");
          MySqlCommand cmdSO = new MySqlCommand (cmdStandort, conSO);
          
          cmdSO.Parameters.AddWithValue("Kostenstelle", SqlDbType.Int).Value = "Kostenstelle";
          //cmdSO.Parameters.AddWithValue("Kostenstelle", cbKostenstelle.SelectedItem);


Änderungen mal hervorgehoben.

Entspricht dieses "Kostenstelle" bei ".Value = "Kostenstelle";" Nun meiner Spalte in der DB?
Da bin ich nun ein bischen durcheinander.

Er soll mir ja in die Abfrage den Wert aus der Combobox "Kostenstelle" einbauen um entsprechend den Standort einzutragen.

Oder übersehe ich jetzt komplett etwas? :?
san-software
Hält's aus hier
Beiträge: 11
Erhaltene Danke: 3



BeitragVerfasst: Do 25.04.13 16:15 
Zitat:
Entspricht dieses "Kostenstelle" bei ".Value = "Kostenstelle";" Nun meiner Spalte in der DB?


ja aber:

Zitat:
SqlDbType.Int).Value = "Kostenstelle";


so wirst du nicht finden, denn Du suchst hier nach der Kostenstelle mit der ID "Kostenstelle".
Du mußt ja nach der selektierten Kostenstelle (also nach dem Inhalt deiner Selektierten Zeile in der Combobox) suchen.

Der Ansatz

Zitat:
string cmdStandort = ("SELECT Standort FROM Inventar WHERE Kostenstelle = 0002");


war schon richtig.

Aber ich würde dir raten, erst einaml die Datenbank, so wie ich schon beschrieben hatte gerade zu ziehen.
Sonst fangen wir dann noch mal von Vorne an.

Für diesen Beitrag haben gedankt: .c0dy
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 25.04.13 16:52 
Zitat:
cmdSO.Parameters.AddWithValue("Kostenstelle", SqlDbType.Int).Value = "Kostenstelle";


Bei AddWithValue geht der ParameterName und der Wert rein. Du brauchst den Typ also nicht mit anzugeben der wird anhand des übergebenen Wert Objektes automatisch ermittelt.

ausblenden C#-Quelltext
1:
2:
3:
4:
Int32 value; 
if (!Int32.TryParse(meineLiebeCombobox.Text, out value)) // wenn in der Combobox führende 0'en waren sind die jetzt weg
   throw new Exception("ungültige Kostenstelle");
cmdSO.Parameters.AddWithValue("@Kostenstelle", value);

Für diesen Beitrag haben gedankt: .c0dy
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Do 25.04.13 18:14 
Danke für die Antworten :)

Die Datenbank habe ich nun dementsprechend angepasst.

Ich kenne es von damals aus der Schule noch so, dass man in die Abfrage gleich eine Variable einbauen kann ("SELECT "+ variableXY +" FROM Blubb"). Allerdings habe ich diesbezüglich gelesen, dass das eine Möglichkeit für eine SQL-Injection bietet.

Das wäre zwar nicht sonderlich tragisch, da das Programm aber als Projekt vorgestellt wird, wäre es natürlich von Vorteil sagen zu können "Das hab ich so und so gemacht um dies und das zu verhindern".
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Do 16.05.13 15:25 
Hallo, liebe Leute :)

Mein Programm ist nun fast fertig. Zwei Sachen fehlen mir noch. Eine davon erstmal nur Optional.

Meine Combo- und Textboxen funktionieren jetzt wunderbar als Filter für die eine meiner DataGridView.

Jetzt möchte ich allerdings entweder:

a) Die Datenbank direkt über die DataGridView bearbeiten (was wahrscheinlich vom Codeaufwand einfacher ist)

b) Das ganze über einen Button zu machen und die entsprechende Änderung an die Datenbank zu "senden".

Habe es schon mit DataAdapter.Update versucht, allerdings scheint da nichts an die Datenbank zu kommen.1

Beim Laden des Programmes passiert nun folgendes (zur näheren Information):

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
        MySqlConnection sqlConnection = new MySqlConnection(dbconnect);
            selectQueryStringInventar = "SELECT * FROM inventar ORDER BY Kostenstelle;";
            sqlConnection.Open();

            MySqlDataAdapter sqlDataAdapter = new MySqlDataAdapter(selectQueryStringInventar, sqlConnection);
            MySqlCommandBuilder sqlCommandBuilder = new MySqlCommandBuilder(sqlDataAdapter);

            DataTable dataTableInventar = new DataTable();
            sqlDataAdapter.Fill(dataTableInventar);
            bindingSource = new BindingSource();
            bindingSource.DataSource = dataTableInventar;

            dataGridInventar.DataSource = bindingSource;
            
            
            
            //Verarbeitung für die Versandtliste
            
            selectQueryStringVersandt = "SELECT * FROM versandt;";
            

            MySqlDataAdapter sqlDataAdapterVersandt = new MySqlDataAdapter(selectQueryStringVersandt, sqlConnection);
            MySqlCommandBuilder sqlCommandBuilderVersandt = new MySqlCommandBuilder(sqlDataAdapterVersandt);

            DataTable dataTableVersandt = new DataTable();
            sqlDataAdapterVersandt.Fill(dataTableVersandt);
            BindingSource bindingSourceVersandt = new BindingSource();
            bindingSourceVersandt.DataSource = dataTableVersandt;

            dataGridVersandt.DataSource = bindingSourceVersandt;
            
            
            }


Die Methode mit dem DataAdapter.Update hatte ich wie gesagt schon getestet. Allerdings kommt da nichts bei über.
Hab schon diverse Google-Suchen getätigt und mir diverse Hinweise angesehen, aber irgendwie scheitert es dann doch an der Umsetzung.

Vielleicht könnt ihr mir da ja auch nochmal helfen :)

Vielen Dank im Voraus :)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 16.05.13 19:18 
Hallo,

rufe mal folgende Methode von deinem Button-Click aus:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
private int UpdateData(string sConnection, DataSet dataset, IDbDataAdapter data_adapter)
{
        if(dataset.Tables.Count == 0 || dataset.Tables[0].Rows.Count == 0)
            return -1;

        SqlCommandBuilder cb = new SqlCommandBuilder(data_adapter as SqlDataAdapter);

        data_adapter.SelectCommand.Connection.ConnectionString = sConnection;

        data_adapter.DeleteCommand = cb.GetDeleteCommand(true);
        data_adapter.InsertCommand = cb.GetInsertCommand(true);
        data_adapter.UpdateCommand = cb.GetUpdateCommand(true);

        try
        {
            return data_adapter.Update(dataset);
        }
        catch(Exception ex)
        {
            MessageBox.Show(this, ex.Message, "Database Error");
            return -1;
        }
}

Ist schon etwas länger her, daß ich selber damit gearbeitet habe ;-)
Statt dem DataSet kannst du diese Methode auch so umschreiben, daß sie eine DataTable benutzt. Und statt den Klassen für den MS SQL Server, dann die entsprechenden für deine Datenbank MySql (also MySqlCommandBuilder).

Wichtig ist aber, daß du den DataAdapter sowie das DataSet (bzw. DataTable) in deinem Programm als Membervariable hältst (anstatt bisher als lokale Variable), damit Laden und Updaten auf derselben Instanz passieren!

Für diesen Beitrag haben gedankt: .c0dy
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Di 21.05.13 12:51 
Tut mir leid, dass ich mich erst jetzt melde.
Lag leider flach und bin derzeit noch ganz schön mit meiner Dokumentation beschäftigt.

Danke schonmal für die Antwort :)
Ich werde mir das dann bei nächster Gelegenheit mal anschauen und euch dann nochmal berichten oder vielleicht auch belästigen :D
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Mo 10.06.13 01:04 
Und da bin ich auch nochmal :)

Ich bin mitlerweile schon ein wenig verzweifelt und habe das eine oder andere Haar verloren oder es grau gefärbt :P

Ich habe hier jetzt mal einfach den kompletten Code "hochgeladen".

pastebin.com/sC3BLThC

Ich habe die vorher gepostete Methode ausprobiert, stehe aber entweder total auf dem Schlauch und stell mich echt dümmer an als es geht, hab leider oft genug das Problem, dass ich mir die Sachen schwerer mache als sie sind und im Endeffekt einfach überhaupt nichts mehr kapiere :/ - habe es wie gesagt versucht umzusetzen.

Leider bisher ohne Erfolg. Habe auch diverse andere Sachen ausprobiert. Wie dem auskommentierten Code unter "public void BtnSpeichernClick(object sender, EventArgs e)" zu entnehmen.

Dort war leider das Problem, dass die dataTable beim Updaten auf "null" stand. Nur mir war es leider nicht logisch zu erkennen, WARUM. Denn durch ein bischen googlen habe ich gesehen, dass man die dataTable auch wieder von den Werten "befreien" kann. Was ich ja aber auch niergends gemacht habe.

Oder ist mein Programm dafür einfach zu besch..eiden aufgebaut?

Ich würde mich riesig freuen, wenn mir da nochmal jemand Licht ins Dunkle bringen könnte.

Mit freundlichen Grüßen

.c0dy :)

EDIT: Ich schätze es ist einiges evtl. "doppelt-gemoppelt".
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 10.06.13 09:22 
Hallo .c0dy,

ich wiederhole mich mal:
Th69 hat folgendes geschrieben:
Wichtig ist aber, daß du den DataAdapter sowie das DataSet (bzw. DataTable) in deinem Programm als Membervariable hältst (anstatt bisher als lokale Variable), damit Laden und Updaten auf derselben Instanz passieren!

Du darfst also nicht in jeder Methode diese Variablen wieder neu anlegen, sondern nur jeweils die Membervariablen benutzen! (Dadurch wird dein Code auch wieder ein bißchen kleiner und übersichtlicher).

Für diesen Beitrag haben gedankt: .c0dy
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Mo 10.06.13 09:42 
Also müsste ich dann doch

ausblenden C#-Quelltext
1:
MySqlDataAdapter sqlDataAdapterVersand = new MySqlDataAdapter(selectQueryStringVersand, sqlConnection);					


Mit hier hin nehmen

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
public partial class Programm : Form
  {
    
    
    String selectQueryStringInventar = null;
    String selectQueryStringVersand = null;
    
    private MySqlCommandBuilder sqlCommandBuilder = null;
    MySqlConnection sqlConnection = new MySqlConnection(dbconnect);
    
    private MySqlDataAdapter sqlDataAdapterInventar = null;
    
    private DataTable dataTableInventar = null;
    private BindingSource bindingSourceInventar = null;
    

    
    private DataTable dataTableVersand = null;
    private BindingSource bindingSourceVersand = null;


Oder habe ich nun wieder einen Denkfehler O_O

Wenn ich das nämlich mache, meckert er mir rum, dass ich dort nicht gleich (selectQueryStringVersand, sqlConnection) mitgeben kann.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 10.06.13 11:42 
Hallo .c0dy,

das sind aber nun einfache Grundlagen - vllt. solltest du doch eher ein C#-Buch durcharbeiten und kleinere Programme schreiben, anstatt gleich eine WinForms-Anwendung mit Datenbankzugriff.

Die Initialisierung der Membervariablen mußt du in einer Methode vornehmen (z.B. im Konstruktor oder aber im Load-Ereignis).
.c0dy Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Mo 10.06.13 12:43 
Wie gesagt/geschrieben, hatte ich vor einiger Zeit das letzte mal mit C# gearbeitet.

Das man da das eine oder andere mal evtl. auf dem Schlauch steht, kann doch mal vorkommen ;)

Hatte damals auch mit WinForms und SQL gearbeitet, allerdings nicht mit DataGridView und DataTable.

Und da alles andere funktioniert, bis auf die Updates zur Datenbank schieben, dachte ich das es eventuell doch nur eine Kleinigkeit ist und es für die Routinierten-Leute hier möglich ist mir das ganze evtl. zu Erläutern und evtl zu sagen "schieb das und das da hin, dann sollte es funktionieren".

Aber danke trotzdem ;)