dringendes (und merkwürdiges) Problem mit DataSet, DataBinding und Update
-
Hallo zusammen!
Ich habe ein etwas merkwürdiges Problem, an dem ich völlig verzweifele (u.a. weil ich sehr viel Zeitdruck hab, und schon sehr viel Zeit in dieses Problem investiert habe)
Ich bin für jegliche Hilfe EXTREM dankbar!!Ich benutze einen ODBCDataAdapter (mit selbstgebastelen Select, Update ect Commands), ein untypisiertes DataSet und eine Access DB.
In meinem Fenster ist eine Listbox, die mir per Binding Firmennamen anzeigt.Darunter sind Textboxen für die Firmendetails
Wähle ich einen aus, werden unten die Details der Firma angezeigt. Das ganze funzt einwandfrei per DataBinding.
Nun gehts aber los:
Ich wähle eine Firma aus. Ich ändere ihren Namen.
Wenn ich nun firmsDataSet.HasChanges() abfrage, sagt er mir keine Änderung. Obwohl die Änderung im DataSet ist (das sehe ich wenn sie mir in eine XML Datei schreiben lasse).
Die einzige Möglichkeit, die mein DataSet davon überzeugt, die RowState Property richtig zu setzen, ist wenn ich in der Listbox NACH der Ändernung den SelectedIndex auf -1 (also keines) setze. DANN ergibt HasChanges true, und per Binding wird auch der neue Name in der Listbox angezeigt
Aber als wenn nun alles gehen würde...
Rufe ich nun die Update-Methode des DataAdapters auf, bekomme ich den ERROR [HY090] - Ungültige Zeichen oder Pufferlänge.
Aber an dem UpdateCommand des Adapters kann es aber eigentlich nicht liegen, denn wenn ich einfach updateCom.ExecuteNonQuery(); aufrufe, updated er die Datenbank (mit falschen Daten, aber das liegt wohl an meiner Parameterzuweisung), ABER der Name in der Listbox wird NICHT geändert (im Textfeld Name darunter aber wird wiederum der richtige angezeigt).So hier der Code:
Zuerst die DataBindings:
this.lstBx_Firmen.DataSource = Ergo.MainApp._FirmDB._FirmsDataSet; this.lstBx_Firmen.DisplayMember = "Firmen.Name"; this.txtBx_Name.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Name"); this.txtBx_Zusatz.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Zusatz"); this.txtBx_Straße.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Straße"); this.txtBx_Ort.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Ort"); this.txtBx_PLZ.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.PLZ"); this.txtBx_Postfach.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Postfach"); this.txtBx_Tel.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Tel_Nr"); this.txtBx_Fax.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Fax_Nr"); this.txtBx_Mobil.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.Mobil_Nr"); this.txtBx_Mail.DataBindings.Add("Text", Ergo.MainApp._FirmDB._FirmsDataSet, "Firmen.E_Mail");
ohne diese Zeile weigert sich das DataSet, jegliche Änderung anzuerkennen:
this.lstBx_Firmen.SelectedIndex = -1;
hier der Init des Adapters und des DataSets (Insert/Delete Teil weggelassen):
private void BuildUpDataSet() { firmsDataAdapter = new OdbcDataAdapter(); firmsDataSet = new DataSet("FirmenDataSet"); // ============== // SELECT command // ============== string selectStr = "SELECT * FROM Firmen"; OdbcCommand selectCom = new OdbcCommand(selectStr, Ergo.MainApp._ErgoDB._MyConnection); // ============== // UPDATE command // ============== string updateStr = "UPDATE Firmen SET " + "Name = ?, Zusatz = ?, Ort = ?, PLZ = ?, " + "Postfach = ?, Straße = ?, Tel_Nr = ?, " + "Fax_Nr =?, Mobil_Nr = ?, E_Mail = ? " + "WHERE ID_Firma = ? "; updateCom = new OdbcCommand(updateStr, Ergo.MainApp._ErgoDB._MyConnection); // add the parameters to the collection updateCom.Parameters.Add("Name", OdbcType.Text, 50, "Firmen.Name"); updateCom.Parameters.Add("Zusatz", OdbcType.Text, 100, "Firmen.Zusatz"); updateCom.Parameters.Add("Ort", OdbcType.Text, 50, "Firmen.Ort"); updateCom.Parameters.Add("PLZ", OdbcType.Text, 50, "Firmen.PLZ"); updateCom.Parameters.Add("Postfach", OdbcType.Text,50, "Firmen.Postfach"); updateCom.Parameters.Add("Straße", OdbcType.Text, 100, "Firmen.Straße"); updateCom.Parameters.Add("Tel_Nr", OdbcType.Text, 50, "Firmen.Tel_Nr"); updateCom.Parameters.Add("Fax_Nr", OdbcType.Text, 50, "Firmen.Fax_Nr"); updateCom.Parameters.Add("Mobil_Nr", OdbcType.Text,50, "Firmen.Mobil_Nr"); updateCom.Parameters.Add("E_Mail", OdbcType.Text, 50, "Firmen.E_Mail"); // add the primary key parameter OdbcParameter pU = new OdbcParameter("ID_Firma", OdbcType.Int, 50, "Firmen.ID_Firma"); pU.SourceVersion = DataRowVersion.Original; updateCom.Parameters.Add(pU); // fill the dataSet try { firmsDataAdapter.Fill(firmsDataSet, "Firmen"); } catch(OdbcException ex) { MessageBox.Show(ex.Message, "Fehler beim Füllen des DataSets"); } // set primary key column DataColumn [] keys = new DataColumn[1]; keys[0] = firmsDataSet.Tables["Firmen"].Columns["ID_Firma"]; firmsDataSet.Tables["Firmen"].PrimaryKey = keys; }
und hier schließlich das vermeindliche Datenbank Update:
try { string firmID = GetFirmID(oldName); // gibt mir den primary key der ausgewählten Firma, das funktioniert auch if (firmID != null)// && (CheckValues(newName))) { // die explizite Wertzuweisung an die Parameter würde ich mir SEHR gerne sparen // aber dann geht es nicht, Der DataAdapter holt sich nicht selbstständig die // neuen Werte aus dem DataSet firmsDataAdapter.UpdateCommand.Parameters["Name"].Value = newName; firmsDataAdapter.UpdateCommand.Parameters["Zusatz"].Value = newZusatz; firmsDataAdapter.UpdateCommand.Parameters["Ort"].Value = newOrt; firmsDataAdapter.UpdateCommand.Parameters["Postfach"].Value = newPostfach; firmsDataAdapter.UpdateCommand.Parameters["PLZ"].Value = newPLZ; firmsDataAdapter.UpdateCommand.Parameters["Straße"].Value = newStraße; firmsDataAdapter.UpdateCommand.Parameters["Tel_Nr"].Value = newTel; firmsDataAdapter.UpdateCommand.Parameters["Fax_Nr"].Value = newFax; firmsDataAdapter.UpdateCommand.Parameters["Mobil_Nr"].Value = newMobil; firmsDataAdapter.UpdateCommand.Parameters["E_Mail"].Value = newMail; firmsDataAdapter.UpdateCommand.Parameters["ID_Firma"].Value = firmID; if (firmsDataSet.HasChanges()) MessageBox.Show("Bingo"); firmsDataSet.WriteXml("FirmsDataSet"); // hier kommt die Fehlermeldung, vorrausgesetzt das DataSet akzeptiert, das es geändert wurde firmsDataAdapter.Update(firmsDataSet, "Firmen"); // dieser Befehl gibt keine Fehlermeldung, sondern aktualisiert die Datenbank //updateCom.ExecuteNonQuery(); } catch ...
Sorry für dieses überlage Post, aber ich hab alles reingehauen, wo der Fehler sein könnte.
P.S.: Alles was mit _ anfängt ist eine Property. Der obige Code ist verteilt über die Klasse des GUIs und eine dazugehörende DB-Anbindungsklasse.
-
um nochmal die verschiedenen "Szenarien" zu nennen:
lasse ich diese Zeile
this.lstBx_Firmen.SelectedIndex = -1;
weg, und benutze diese
updateCom.ExecuteNonQuery();
für den Update zur Datenbank, kommen sie auch dort an.
Das DataSet bekommt sie auch (in der XML Datei erscheinen sie), aber gleichzeitig bleibt das DataSet bei der Meinung, es wäre nicht geändert worden... ?!?!?wenn ich andersherum diese Zeile
this.lstBx_Firmen.SelectedIndex = -1;
drinlasse, und den Update per
firmsDataAdapter.Update(firmsDataSet, "Firmen");
ausführe, bekomme ich die Fehlermeldung
"ERROR [HY090] - Ungültige Zeichen oder Pufferlänge".
also irgendwo ist doch da gewaltig der Wurm drin.
Warum weigert sich das DataSet, die Änderung, die es ja bekommt, als solche wahrzunehmen?
-
naja falls einen die Lösung interessiert:
-
OleDb statt Odbc und schon enden die komischen Fehlermeldungen der DB
-
vor der Update Methode BindingContext[DataSet, Tablename].EndCurrentEdit() aufrufen und das DataSet markiert sich auch brav als geändert
-
dazu der Commandbuilder, der dank OleDb nun funzt, und die Sache ist gegessen....
-