Autor |
Beitrag |
garv3
      
Beiträge: 33
|
Verfasst: Mi 26.08.09 15:05
Hallo zusammen!
Habe hier ein Problem mit einer Datenbankabfrage. Bei folgendem Code wird mir für die Zeile 22 untenstehender Fehler angezeigt. Die anderen SqlCeCommand() Anweisungen funktionieren aber! Woran liegt das bitte? Denn die Tabelle ist vorhanden und hat auch die entsprechenden Spalten. Sie ist allerdings leer. Wenn ich Zeile 22 u.a. auskommentiere, bekomme ich den selben Fehler für Zeile 30!
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:
| public void speichere_Buchungen() { oeffne_db();
sql_cmd = new SqlCeCommand("SELECT * FROM aktuelleBuchungen ORDER BY Zeit ASC", sql_con); SqlCeDataReader sql_result = sql_cmd.ExecuteReader(); sql_result = sql_cmd.ExecuteReader(); int counti = 0; while (sql_result.Read()) { sql_cmd = new SqlCeCommand("INSERT INTO Buchungen (Artikel, Anzahl, Tisch, Kellner, Preis, Zeit, ist_reduziert) VALUES ( " + Convert.ToInt32(sql_result["Artikel"]) + ", " + Convert.ToInt32(sql_result["Anzahl"]) + ", " + Convert.ToDecimal(sql_result["Tisch"]).ToString().Replace(",", ".") + ", " + Convert.ToInt32(sql_result["Kellner"]) + ", " + Convert.ToDecimal(sql_result["Preis"]).ToString().Replace(",", ".") + ", GETDATE(), " + Convert.ToInt32(sql_result["ist_reduziert"]) + " )", sql_con); sql_cmd.ExecuteNonQuery(); sql_cmd = new SqlCeCommand("DELETE FROM aktuelleBuchungen WHERE id = "+Convert.ToInt32(sql_result["id"])+";", sql_con); sql_cmd.ExecuteNonQuery(); counti++; } sql_cmd.Dispose(); sql_result.Dispose(); if (counti > 0) { sql_cmd = new SqlCeCommand("SELECT Tisch, Kellner FROM besetzteTische WHERE Tisch = " + Convert.ToDecimal(sql_result["Tisch"]).ToString().Replace(",", ".") + " AND Kellner = " + Convert.ToInt32(kellner_nummer), sql_con); sql_result = sql_cmd.ExecuteReader(); if (sql_result.Read()) { } else { sql_cmd = new SqlCeCommand("INSERT INTO besetzteTische (Tisch, Kellner) VALUES (" + Convert.ToDecimal(sql_result["Tisch"]).ToString().Replace(",", ".") + ", " + Convert.ToInt32(kellner_nummer) + ")", sql_con); sql_cmd.ExecuteNonQuery(); } } sql_cmd.Dispose(); schliesse_db(); StornoButton.Enabled = false; AktuelleBuchungZeile1.Text = ""; AktuelleBuchungZeile2.Text = ""; aktualisiere_bereits_gebucht(); } |
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:
| System.InvalidOperationException wurde nicht behandelt. Message="Für die Zeile/Spalte sind keine Daten vorhanden." Source="System.Data.SqlServerCe" StackTrace: bei System.Data.SqlServerCe.SqlCeDataReader.GetOrdinal(String name) bei System.Data.SqlServerCe.SqlCeDataReader.get_Item(String name) bei Kasse.Form1.speichere_Buchungen() in C:\Users\Garvin\Documents\Visual Studio 2008\Projects\Kasse\Kasse\Form1.cs:Zeile 919. bei Kasse.Form1.TasteTisch_Click(Object sender, EventArgs e) in C:\Users\Garvin\Documents\Visual Studio 2008\Projects\Kasse\Kasse\Form1.cs:Zeile 560. bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) bei System.Windows.Forms.Application.Run(Form mainForm) bei Kasse.Program.Main() in C:\Users\Garvin\Documents\Visual Studio 2008\Projects\Kasse\Kasse\Program.cs:Zeile 18. bei System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() bei System.Threading.ThreadHelper.ThreadStart_Context(Object state) bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) bei System.Threading.ThreadHelper.ThreadStart() InnerException: |
Ich hoffe, jemand kann mir helfen!
Dank und Gruß
garv3
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mi 26.08.09 15:28
Hallo,
in Zeile 19 steht bereits sql_result.Dispose(); dann kann anschließend auf sql_result nicht mehr zugegriffen werden.
Ich halte es auch für zumindest kritisch, ständig zwischen ExecuteReader und ExecuteNonQuery zu wechseln. Das mag zwar in deiner Situation gerechtfertigt sein; aber wegen der Zusatzbedingung (Reader blockiert gern Connection) musst du sauber trennen und die später benötigten Variablen zwischenspeichern. Das vermeidet auch solch unsägliche Konstruktionen mit mehrfachem Hin- und Herkonvertieren:
C#-Quelltext 1:
| Convert.ToDecimal(sql_result["Tisch"]).ToString().Replace(",", ".") |
Bei der Gelegenheit beachte unbedingt:
juetho hat folgendes geschrieben: | Benutze für variable Inhalte eines SQL-Befehls niemals String-Verknüpfung, sondern immer DbParameter! |
Einzelheiten dazu siehe z.B. [Artikelserie] Parameter von SQL Befehlen. Das vermeidet solche Konstruktionen, zumal du es falsch machst: Du benutzt in Convert.ToInt32(kellner_nummer) eine Zahl, nämlich kellner_nummer (ich nehme jedenfalls an, dass das wirklich eine Zahl ist) und konvertierst sie überflüssigerweise in einen Int32, aber innerhalb der String-Verknüpfung wird ein String verlangt. Statt korrekter wird es quätscher!
Gruß Jürgen
|
|
garv3 
      
Beiträge: 33
|
Verfasst: Mi 26.08.09 16:19
Danke erstmal für die Antwort!
Doch auch ohne die Zeilen 18 und 19 bekomme ich die selbe Fehlermeldung! Natürlich war das sql_result.Dispose(); in Zeile 19 quatsch! Dennoch geht es noch nicht... Aber das ist auch logisch, denn ich bin ja nicht mehr in der sql_result.Read()-Schleife... Da ist wohl ein kleiner Denkfehler drin.
Aber DANKE!
garv3
P.S. Durch die Datentypen für Datenbanken bin ich bis jetzt wirklich noch nich durchgestiegen. Wenn ich z.B. eine Dezimalzahl wie "3,24" habe, nimmt sql die im String nicht an, da es denkt, es wäre ein neuer Parameter. Gibt es sowas wie mysql_real_escape_string() bei php auch unter C#?
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mi 26.08.09 18:04
Zum Problem und der Fehlermeldung: Nach dem Ende der while-Schleife ist der Reader abgeschlossen; es gibt also keine weiteren Zeilen, er steht sozusagen "hinter der letzten Zeile", und dort gibt es keine Daten mehr, die für die weitere Verarbeitung verwendet werden könnten.
Als Lösung hatte ich schon gesagt: Speichere die später benötigten Daten in weiteren passenden Variablen.
Dein Beispiel "3,24" ist ein String mit Komma. Der hat als String im SQL-String nichts zu suchen, weil das Komma (wie du richtig erkannst hast) den Befehl kaputtmacht. Wenn du die dazugehörige Dezimalzahl meinst, dann darf die allenfalls so im SQL-String stehen, dass die Datenbank bzw. der DbProvider das als Zahl erkennt, also z.B. als 3.24.
Aber genau diese Probleme werden vermieden, wenn man DbParameter benutzt. Parameter, Parameter!
Jürgen
|
|
|