Laden...

Problem mit Formatierung eines Strings in eine Zahl und INSERT mittels SQL

Erstellt von FraBam vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.255 Views
F
FraBam Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren
Problem mit Formatierung eines Strings in eine Zahl und INSERT mittels SQL

Hallo liebe Prgrammierer,

beschäftige mit seit ein paar Monaten mit C# und verzweifle mit folgendem Programmcode.

Ich errechne zunächst aus einem DataGridView die Gesamtsumme einer Spalte, formatiere diese und übergebe das Ergebnis an eine TextBox.


 private void NettowertSummieren(DataGridView dataGridView, TextBox textBox)
        {
            int result=0;

            for (int i = 0; i < dataGridView.Rows.Count; i++)
            {
            
                    result += Convert.ToInt32(dataGridView.Rows[i].Cells["Nettowert"].Value);
            }

            textBox.Text =  string.Format("{0:#,##0.00}", result);

        }

Im Anschluss rufe ich eine Methode auf, mit der ich den Wert aus der TextBox (txbNettowertKd) in eine Access Datenbank speichern will. Dieser Aufruf ruft bringt die Fehlermeldung "System.FormatException". Wenn ich die obige Formatierung auf textBox.Text = result.ToString(); ändere, funktioniert der Aufruf ohne Fehlermeldung.


public void WriteDatabase()
        {
            databaseDAL.OpenDatabase();
            databaseDAL.DbDeleteValue(txbDatum.Text);
            databaseDAL.DbWriteValue(user, Convert.ToDateTime(txbDatum.Text).Date, txtBoxPath.Text, Convert.ToInt32(txbNettowertKd.Text)); 
            databaseDAL.CloseDatabase();
        }



Die Methode selbst sieht wie folgt aus:

public void DbWriteValue(string user, DateTime datum, string path, int nettowertKd)
        {

            string sql = "INSERT INTO tbl_01_UploadHistorie ( [User], Datum, Dateiname, KdWert) " +
                            "VALUES ('" + user + "', '" + datum + "', '" + path + "', " + nettowertKd + ")";
            
            ExecQuery(sql);

        }

Ich habe schon alles mögliche gegoogled. Die Formatierung scheint OK zu sein. Der Wertebereich der int Eigenschaft passt auch. Eine Umwandlung in decimal hat auch nicht geholfen.

Wo liegt mein Gedankenfehler?

Vielen Dank schon mal im voraus.

LG
Christian

16.834 Beiträge seit 2008
vor 3 Jahren

Bitte beachte [Hinweis] Wie poste ich richtig? und pack den Code in BB Tags. Du hast entsprechende Seite vor wenigen Minuten zwei Mal als gelesen akzeptiert.
Niemand hat Lust Plaintext Code zu lesen 😉

Was man aber sofort sieht: [Artikelserie] SQL: Parameter von Befehlen
Ansonsten Hinweis auf [Artikel] Drei-Schichten-Architektur

PS: Access ist keine Datenbank. Bitte nicht dafür missbrauchen.
Wenn Du eine lokale Datenbank willst, die kein extra Server braucht, dann nimm zB Sqlite.

T
2.224 Beiträge seit 2008
vor 3 Jahren

Das Problem ist, dass im deutschen als Dezimaltrennzeichen ein Komma verwendet wird.
Datenbanken verwenden aber den Punkt dafür.
Entsprechend wird das Komma als Trennzeichen in deinem SQL String interpretiert und fliegt weg.

Wie Abt schon schreibt, nimm dafür SQL Parameter.
Dort werden die Werte dann korrekt an die Datenbank geschickt.
Als lokale Datenbank, würde ich dir auch SQLite ans Herz legen.
Mit Access hatte ich zu letzt vor 5-6 Jahren zu tun und das war immer ein Krampf.
Im .NET Bereich gibt es genug saubere lokale Datenbank Lösungen wie SQLite.

Nachtrag:
Du solltest deinen Nettowert auch nicht als Int an die Datenbank geben.
Int kennt keine Dezimalstellen, also wird aus 9,99€ plötzlich 9,00€.
Schau dir am besten die Doku für die Datentypen von .NET nochmal an!

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

F
FraBam Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren

Hallo Abt,

danke für die Hinweise. Werde ich beim nächsten Mal berücksichtigen.

Christian

16.834 Beiträge seit 2008
vor 3 Jahren

Wäre nett wenn Du auch der Bitte Dein Beitrag zu formatieren nachkommen würdest. 👍
Hast nen Edit Button am Beitrag.

F
FraBam Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren

Hallo T-Virus,

danke für die Info. Ich habe weiter getestet und bin darauf gekommen, dass das eigentlich noch nichts mit der Datenbank sondern vielmehr mit der eigentlichen Konvertierung string zu int zu tun hat. Vermute, ich muss mich mehr mit den Grundlagen auseinandersetzen.

Christian

16.834 Beiträge seit 2008
vor 3 Jahren

Das hat was damit zutun, dass Du mit den Datentypen falsch umgehst; ausgelöst weil Du keine SQL Parameter verwendest.
Daher auch entsprechend der Link zur FAQ.

F
FraBam Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren

@Abt

Ja, du hast Recht. Bin zwischenzeitlich auf den Fehler gekommen. Habe die Eigenschaft result von int auf decimal umgestellt und siehe da, es funktioniert. Mit dem SQL hat es eigentlich gar nichts zu tun gehabt. Die Verwendung von SQL Parametern werde ich mir aber zur Herzen nehmen.


private void NettowertSummieren(DataGridView dataGridView, TextBox textBox)
        {
            decimal result=0;

            for (int i = 0; i < dataGridView.Rows.Count; i++)
            {
            
                    result += Convert.ToDecimal(dataGridView.Rows[i].Cells["Nettowert"].Value);
            }

            textBox.Text =   string.Format("{0:#,##}", result); 


        }

T
2.224 Beiträge seit 2008
vor 3 Jahren

Natürlich hat es auch mit den SQL Parametern zu tun.
Ohne diese öffnest du deiner Datenbank auch noch für SQL Injections.

Lies dich in der Doku dazu ein und stell deinen Code um.
Sonst läufst du noch auf viel mehr Probleme, die durch selbst gebastelte Strings als SQL auftauchen.
Hier gibt es noch weitere Datentypen, die sich mit deutschen Formaten nicht vertragen.
Solche Probleme kann man mit SQL Parametern erschlagen, da die Datenbank diese dann im korrekten Format bekommt und speichern kann.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

F
FraBam Themenstarter:in
10 Beiträge seit 2020
vor 3 Jahren

Vielen Dank zunächst für die vielen Hinweise. Das hat mir echt weitergeholfen.

Den Code habe ich zwischenzeitlich auf Parameter umgestellt. Gefällt mir auch wesentlich besser und nicht so ein Gefummel beim Zusammenbasteln des SQL String 😃


public void DbWriteValue(string user, DateTime datum, string path, decimal nettowertKd, decimal anzahlKd, decimal nettowertPg, decimal anzahlPg)
        {
            string sql = "INSERT INTO tbl_01_UploadHistorie ( [User], Datum, Dateiname, KdWert, KdAnzahl, PgWert, PgAnzahl) " +
                           "VALUES (@User, @Datum, @Path, @KdWert, @KdAnzahl, @PgWert, @PgAnzahl)";

            OleDbCommand cmd = new OleDbCommand(sql, this.conn);

            cmd.Parameters.Add("@User", OleDbType.Char).Value = user;
            cmd.Parameters.Add("@Datum", OleDbType.DBDate).Value = datum;
            cmd.Parameters.Add("@Path", OleDbType.Char).Value = path;
            cmd.Parameters.Add("@KdWert", OleDbType.Decimal).Value = nettowertKd;
            cmd.Parameters.Add("@KdAnzahl", OleDbType.Decimal).Value = anzahlKd;
            cmd.Parameters.Add("@PgWert", OleDbType.Decimal).Value = nettowertPg;
            cmd.Parameters.Add("@PgAnzahl", OleDbType.Decimal).Value = anzahlPg;


            try
            {
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }