Eigene Klasse - erster Versuch



  • Hallo zusammen,
    ich habe gerade mit C# angefangen und möchte nun meine erste Klasse erstellen.
    Leider erhalte ich die Fehlermeldung

    Nicht alle Codepfade geben einen Wert zurück

    Wie ich gelesen habe, liegt es wohl daran, dass ein return fehlt??
    Eigentlich dachte ich, dass ich das eingebaut habe?! Vielleicht kann sich das ja mal jemand anschauen und mir sagen, was fehlt? Würde mich auf jeden Fall sehr darüber freuen!

    public class werkzeugliste
        {
            MySqlConnection conn;
    
            public int werkzeugPruefen(string maschine, string werkzeug)
            {
                try
                {
                    conn = new MySqlConnection("Database= '" + Program.DB + "';Data Source=server1;User Id=abc;Password=abc;");
                    int returnWert;
    
                    MySqlCommand cmd = new MySqlCommand();
                    cmd.CommandText = "SELECT wert FROM maschinen, werkzeuge " +
                                      "WHERE maschinen.m_nr = werkzeuge.m_nr " +
                                      "AND maschine.typ = '" + maschine + "' " +
                                      "AND werkzeug.typ = '" + werkzeug + "' " +
    								  "AND maschine.ldid = 2";
                    cmd.Connection = conn;
                    conn.Open();
                    returnWert = (int)(cmd.Parameters[0].Value);
                    conn.Close();
                    return returnWert;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
    
        }
    

    Aufruf der Klasse:

    werkzeugliste wListe = new werkzeugliste();
                MessageBox.Show(wListe.werkzeugPruefen("MF70 Proxxon","Diamant Stift Ø 2,35 mm").ToString());
    


  • Nach dem Catch-Block läuft die Funktion weiter und dort gibts dann kein Return 🙂

    Dirty Quick-Fix? Am Ende der Funktion einfach ein return 0; reinknallen.



  • AnjaMerk schrieb:

    Nicht alle Codepfade geben einen Wert zurück

    Wie ich gelesen habe, liegt es wohl daran, dass ein return fehlt??
    Eigentlich dachte ich, dass ich das eingebaut habe?!

    Wie /rant/ schon angedeutet hat. Mit Codepfade sind verschiedene Codeverzweigungen gemeint. In deinem Fall ist es ein try-catch Block. Wenn innerhalb der try-Verzweigung eine Ausnahme geworfen wird, wird dein return nie erreicht und das Programm springt in den catch-Block, welcher kein return enthält. Da deine Methode aber gezwungen ist, einen Wert zurückzugeben, musst du immer schauen, dass in allen Fällen ein Wert zurückgegeben wird.



  • <Predigt>

    Command-Strings-Gebastele nach diesem Strick-Muster sind derzeit die Einfallstore Nummer eins (vergl. SQL-Injection).

    Anmerkung: Die Ausrede "... ist ja nur für ein Test(projekt) ..." höre ich immer dann, wenn mal wieder mittels SQL-Injections ein Produktivsystem kompromittiert wurde, weil es "einfach vergessen" wurde, den (bis dahin fehlerfrei funktionierenden) Code zu korrigieren.

    </Predigt>

    ~Erst wenn alle Programmierer eingesperrt und alle Ideen patentiert wurden, werdet ihr merken, dass Juristen nicht programmieren können ...~



  • @schmidt-webdesign.net
    Danke für den Hinweis! 🙂
    Ich bin lernbereit ... wie soll daher die Query richtig aussehen?
    Durch Übergabe von Paramtern?
    Soetwas habe ich mal bei einem INSERT Statement gesehen: ... VALUES (?p1, ?p2) ...



  • Ja genau. sieht dann z.B. so aus:

    using(MySqlCommand cmd = conn.CreateCommand())
    {
      // Nur Platzhalter in der eigentlichen Query:
      cmd.CommandText="INSERT INTO tabelle_bla (kunden_id, vorname, nachname) VALUES (@kunden_id, @vorname, @nachname)";
    
      // ...und dann angeben was die Werte für die Platzhalter sein sollen:
      cmd.Parameters.AddWithValue("@kunden_id",1234);
      cmd.Parameters.AddWithValue("@vorname","Max");
      cmd.Parameters.AddWithValue("@nachname","Mustermann");
    
      // weg damit ;D
      cmd.ExecuteNonQuery();
    }
    


  • AnjaMerk schrieb:

    @schmidt-webdesign.net
    Danke für den Hinweis! 🙂
    Ich bin lernbereit ... wie soll daher die Query richtig aussehen?
    Durch Übergabe von Paramtern?
    Soetwas habe ich mal bei einem INSERT Statement gesehen: ... VALUES (?p1, ?p2) ...

    Probier's doch mal so:

    // Funktioniert dieser Code, hat ihn Dirk Schmidt (http://schmidt-webdesign.net) geschrieben. 
    // Funktioniert er nicht, ist der Autor unbekannt.
    
    using System.Data;
    using System.Data.SqlClient;
    
    ...
    
    public int werkzeugPruefen(string maschine, string werkzeug)
    {
        int ret = 0;
        using (SqlConnection con = new SqlConnection("Database= '" + Program.DB + "';Data Source=server1;User Id=abc;Password=abc;"))
        {
            con.Open();
            using (SqlCommand cmd = new SqlCommand("SELECT wert FROM maschinen WHERE maschine=@1 AND werkzeug=@2", con))
            {
                cmd.Parameters.Add("@1", SqlDbType.NVarChar).Value = maschine;
                cmd.Parameters.Add("@2", SqlDbType.NVarChar).Value = werkzeug;
                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    if (dr.Read())
                        ret = dr.GetInt32(0);
                }
            }
        }
        return ret;
    }
    

    Das Beispiel geht von NVarChar-Datentypen aus. Das muss in deinem Fall ggf. angepasst werden.

    ~Erst wenn alle Programmierer eingesperrt und alle Ideen patentiert wurden, werdet ihr merken, dass Juristen nicht programmieren können ...~



  • So, hab das ganze nun versucht bei mir umzusetzen ...

    Hab für das Füllen der Combobox ne Klasse geschrieben bzw. möchte diese wie folgt füllen (mit hoffentlich "ordentlichem" Code).

    Weiß aber nicht, ob ich das richtig gemacht/verstanden habe, denn es werden keine Werte in die cbx gefüllt.

    Ich übergebe beim Aufruf der Funktion den Namen eines Werkzeugs .... dieser Name soll dann als Parameter @1 in meiner SQL-Query verwendet werden.

    Wenn ich mir mit dem Debugger cmd anzeigen lasse, steht da aber immer @1 und nie ein der übergebene Wert (obwohl dieser aber richtig übergeben wird).

    private void cbxDaten_Fuellen(string werkzeug)
            {
                try
                {
                    cbxDaten.Items.Clear();
                    using (MySqlConnection con = new MySqlConnection("Database= '" + Program.DB + "';Data Source=server1;User Id=abc;Password=abc;"))
                    {
                        con.Open();
                        using (MySqlCommand cmd = new MySqlCommand("SELECT DISTINCT material FROM tblmaterial WHERE werkzeug_name=@1", con))
                        {
                            cmd.Parameters.AddWithValue("@1", werkzeug);
                            using (MySqlDataReader dr = cmd.ExecuteReader())
                            {
                                while (dr.Read())
                                {
                                    if (dr.IsDBNull(0) == false)
                                    {
                                        datenFuellen new_data = new datenFuellen();
                                        new_data.id = dr.GetString(0);
                                        new_data.name = dr.GetString(0);
                                        cbxDaten.Items.Add(new_data);
                                    }
                                }
                            }
                        }
                    }
                }
    ...
    


  • Die Parameter und die Werte (Values) werden genauso (d.h. getrennt) an die Datenbank übergeben, d.h. es gibt keine Möglichkeit mit dem Code-Debugger an den erzeugten SQL-Ausdruck zu kommen.

    Du müßtest aber eine Exception erhalten, denn MySql verwendet das Fragezeichen '?' als Parameterkennzeichen (anstatt '@') - du hast ja schon entsprechende Beispiele gesehen...



  • @Th69
    Nein, ich erhalte leider keine Exception. Es wird nur der while-Block übersprungen und dann die Funktion beendet.
    Noch ne Anfänger-Frage: Wird so ein Block als Methode oder Funktion bezeichnet? 😕



  • (Offtopic: Gibts eigentlich irgendwas um das Parameterzeichen '@'/'?'/':'/... per Code rauszubekommen oder hilft da nur Doku schauen? Wobei MySQL wohl so ziemlich alleine mit dem ? ist, andere DBs verstehen gleich mehrere (meist @ und ?))



  • Ist es außerdem möglich, dass ich mehr als einen Rückgabewert bekomme?



  • Üblicherweise verpackt man mehrere Rückgabewerte einfach in eine Klasse/Struct:

    public class Ergebnis
    {
       public int a=0;
       public int b=0;
    }
    
    public Ergebnis meine_funktion(int a, int b)
    {
       Ergebnis e=new Ergebnis();
       e.a=a;
       e.b=b;
    
       return e;
    }
    
    // ...alternativ gibt es auch out (was in meinen Augen weniger schön ist):
    public bool meine_funktion(int a, int b, out int ra, out int rb)
    {
       ra=a;
       rb=b;
    
       return true; // z.B. als flag das ra und rb berechnet werden konnten und gültig sind
    }
    


  • HAllo Geeky,
    ich hab das jetzt mal so versucht, wie Du mir vorgeschlagen hast:

    public class Datensuche
        {
            public string a;
            public string b;
    
            public Datensuche meine_Suche(string nr)
            {
                Datensuche d = new Datensuche();
    
                using (MySqlConnection conDb = new MySqlConnection("Database= '" + Program.DB + "';Data Source=server1;User Id=abc;Password=abc;"))
                {
                    conDb.Open();
                    using (MySqlCommand cmd = new MySqlCommand("SELECT DISTINCT ben1, ben2 FROM warehousedata WHERE ident = '" + nr + "'", conDb))
                    {
                        using (MySqlDataReader dr = cmd.ExecuteReader())
                        {
                            while (dr.Read())
                            {
                                d.a = dr.GetString(0);
                                d.b = dr.GetString(1);
                                return d;
                            }
                        }
                    }
                    d.a = "Nichts vorhanden";
                    d.b = "Auch nix";
                    return d;
                }
            }
        }
    

    Aufgerufen hab ich es folgendermaßen:

    Datensuche datasearch = new Datensuche();
      datasearch.meine_Suche("GT0052");
      MessageBox.Show(datasearch.a);
    


  • Ganz vergessen:
    Mein Wert kommt beim Aufruf "nicht an".
    D.h. in der Funktion beim Debuggen erhalte ich meinen gewünschten Wert, aber beim Aufruf bleibt meine MessageBox leer ...



  • Du erstellst Datensuche datasearch.
    Dann rufst Du meine_Suche für das datasearch-Objekt auf.
    Innerhalb von meine_Suche erstellst Du ein NEUES DatenSuche-Objekt namens d.
    An d veränderst Du die strings a und b und gibst das Objekt zurück.
    Dieses Objekt geht dann verloren. Du ignorierst ja den Rückgabewert.

    Lösche
    Datensuche d = new Datensuche();
    und ersetze alle d.a und d.b durch this.a und this.b.
    Rückgabeobjekt benötigst Du dann auch nicht mehr.

    Ist natürlich die Frage, ob das wirklich so gewollt war. Dir fehlen einfach zu viel Grundlagen für Datenbankprogrammierung.



  • Habs wie folgt geändert ... einen Rückgabewert brauch ich aber, sonst kommt ne Fehlermeldung "'Nicht alle Codepfade geben einen Wert zurück".

    public class Datensuche
        {
            public string a;
            public string b;
    
            public Datensuche meine_Suche(string nr)
            {
                Datensuche d = new Datensuche();
                using (MySqlConnection conDb = new MySqlConnection("Database= '" + Program.DB + "';Data Source=server1;User Id=abc;Password=abc;"))
                {
                    conDb.Open();
                    using (MySqlCommand cmd = new MySqlCommand("SELECT DISTINCT ben1, ben2 FROM warehousedata WHERE ident = '" + nr + "'", conDb))
                    {
                        using (MySqlDataReader dr = cmd.ExecuteReader())
                        {
                            while (dr.Read())
                            {
                                this.a = dr.GetString(0);
                                this.b = dr.GetString(1);
                            }
                        }
                    }
                    //return;
                }
            }
        }
    

    Dir fehlen einfach zu viel Grundlagen für Datenbankprogrammierung.

    Da gebe ich Dir (leider) recht. 😞
    Aber wir soll ich es lernen, wenn ich nicht Fehler mache bzw. an Beispielen übe?
    Hab mir allerdings "Jetzt lerne ich C#" bestellt, das wird dann ab nächster Woche durchgearbeitet ...



  • AnjaMerk schrieb:

    Habs wie folgt geändert ... einen Rückgabewert brauch ich aber, sonst kommt ne Fehlermeldung "'Nicht alle Codepfade geben einen Wert zurück".

    public void meine_Suche(string nr)

    AnjaMerk schrieb:

    Aber wir soll ich es lernen, wenn ich nicht Fehler mache bzw. an Beispielen übe?

    Mit einfachen Konsolenanwendungen. Ohne Datenbank, GUI, etc. Einfach nur auf das wesentliche konzentrieren und solange üben bis es sitzt. Zum Beispiel jetzt erstmal: Methoden, Parameter und Rückgabewerte. Ist langweilig aber notwendig.


Log in to reply