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
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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.
Hallo Abt,
danke für die Hinweise. Werde ich beim nächsten Mal berücksichtigen.
Christian
Wäre nett wenn Du auch der Bitte Dein Beitrag zu formatieren nachkommen würdest. 👍
Hast nen Edit Button am Beitrag.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
@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);
}
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.
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);
}
}