Laden...

[gelöst] Access übernimmt Werte aus DataBindings nicht

Erstellt von CosmicCode vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.517 Views
C
CosmicCode Themenstarter:in
5 Beiträge seit 2009
vor 14 Jahren
[gelöst] Access übernimmt Werte aus DataBindings nicht

verwendetes Datenbanksystem: OleDb - Access

Hallo zusammen!
Ein mir unerklärliches Phänomen...also:
Eine Access-DB wird über meinen C#-Code angesteuert.
Ich lese die Daten mit .Fill() in ein DataSet, modifiziere diese dort (über ein DataBinding) und schreibe mit .Update wieder in die Access-DB. Seltsamerweise finde ich in Access jedoch keine Änderungen.

BindingSource bs = new BindingSource(); //Neue Quelle für Datenbindung
            bs.DataSource = myds; //Lege das DS "myds" als Datenquelle fest
            bs.DataMember = "Personen";//Lege die Tabelle "Personen" als aktuelle Quelle fest
vornameTextBox.DataBindings.Clear();//Lösche bestehende Bindings
vornameTextBox.DataBindings.Add("Text", bs, "Vorname");//Kopple Text von TextBox an "Vorname"

Um die Funktion des Bindings gegenzuchecken lasse ich mir den Wert vor dem Datenbankzugriff nocheinmal anzeigen und versehe den UpdateCommand mit dem Parameter für den richtigen Datensatz.


Console.WriteLine("Neuer Wert:" + myds.Tables["Personen"].Rows[0]["Vorname"].ToString() + " Wert vom Typ " + myds.Tables["Personen"].Rows[0]["Vorname"].GetType());
oleDbDataAdapter1.UpdateCommand.Parameters.Add("@p1", OleDbType.Integer, 32).Value = personId;
oleDbDataAdapter1.Update(myds);

Im DataSet steht der richtige Wert. Jedoch finde ich diesen nicht in der Access-DB wieder.
Der Abschuss ist dass eine direkte Zuweisung in das DataSet sehr wohl in die DB übernommen wird:


myds.Tables["Personen"].Rows[0]["Vorname"] = "Hanswurscht" ;//Überschreibe sämtliche Binding Werte 
Console.WriteLine("Neuer Wert:" + myds.Tables["Personen"].Rows[0]["Vorname"].ToString() + " Wert vom Typ " + myds.Tables["Personen"].Rows[0]["Vorname"].GetType());
oleDbDataAdapter1.UpdateCommand.Parameters.Add("@p1", OleDbType.Integer, 32).Value = personId;
oleDbDataAdapter1.Update(myds);

Und siehe da: in der DB findet sich ein "Hanswurscht".

Ich hoffe dass das Problem klar geworden ist. Im Prinzip scheint alles zu funktionieren, nur scheint irgendeine Funktion einen Unterschied aus Werten die direkt zugewiesen wurden, und Werten aus DataBindings zu machen.

Ich hoffe ihr könnt mir helfen, und ein herzliches "Servus" an die Kommunity aus dem Oktoberfest-berauschten Bayern

2.223 Beiträge seit 2005
vor 14 Jahren

Hallo CosmicCode und Herzlich Willkommen hier im Forum,

hast du Dir schon einmal das generierte Update SQL angeschaut und es manuell an die Access Datenbank geschickt?

Herzliche Grüße
Lars

J
3.331 Beiträge seit 2006
vor 14 Jahren

Auch ich vermisse den **UpdateCommand **- wie lautet der denn? Zusätzlich könnte es sein, dass BindingSource.EndEdit vor das Speichern gesetzt werden muss. Die Eingabe wird normalerweise erst dann abgeschlossen, wenn der aktive Datensatz gewechselt wird; wenn das Speichern zu früh ausgelöst wird, fehlt dies noch; dann muss per Befehl die Eingabe bewusst beendet werden.

Jürgen

@Lars
Was ist denn mit dem Benutzer blackcoin passiert? Gefiel dir der Name nicht mehr? (Bisher hatte ich leider noch keine Gelegenheit zu dieser Frage.)

C
CosmicCode Themenstarter:in
5 Beiträge seit 2009
vor 14 Jahren

Sooo! Vielen Dank schon einmal für die rasche Reaktion!
juetho!!! 100 Punkte an den Kandidaten mit der Nase im Gesicht!!! 👍
Das Binding beenden war der Schlüssel zum Erfolg! Dankeschön!

Ich habe mir den UpdateCommand (der vom CommandBuilder generiert wurde) trotzdem mal rausgelassen und dieser war in der Tat nicht so wie ich ihn erwartet habe:

UpdateCommand:UPDATE `Personen` SET `Anrede` = ?, `Titel` = ?, `Vorname` = ?, `Name` = ?, `Name_ehemals` = ?, `Geburtsdatum` = ?, `Eintritt` = ?, `Kommentar` = ?, `Mitglied` = ?, `Status` = ?, `Dozent` = ?, `Fortbildung` = ?, `Senior` = ?, `VIP` = ? WHERE ((`ID` = ?) 
AND ((? = 1 AND `Anrede` IS NULL) OR (`Anrede` = ?)) AND ((? = 1 AND `Titel` IS NULL) OR (`Titel` = ?)) AND ((? = 1 AND `Vorname` IS NULL) OR (`Vorname` = ?)) AND ((? = 1 AND `Name` IS NULL) OR (`Name` = ?)) AND ((? = 1 AND `Name_ehemals` IS NULL) OR (`Name_ehemals` = ?)) AND ((? = 1 AND `Geburtsdatum` IS NULL) OR (`Geburtsdatum` = ?)) AND ((? = 1 AND `Eintritt` IS NULL) OR (`Eintritt` = ?)) AND ((? = 1 AND `Kommentar` IS NULL) OR (`Kommentar` = ?)) AND ((? = 1 AND `Mitglied` IS NULL) OR (`Mitglied` = ?)) AND ((? = 1 AND `Status` IS NULL) OR (`Status` = ?)) AND ((? = 1 AND `Dozent` IS NULL) OR (`Dozent` = ?)) AND ((? = 1 AND `Fortbildung` IS NULL) OR (`Fortbildung` = ?)) AND ((? = 1 AND `Senior` IS NULL) OR (`Senior` = ?)) AND ((? = 1 AND `VIP` IS NULL) OR (`VIP` = ?)))

Bis zum WHERE ist mir alles klar...die ID versteht sich von selbst. Nur der Sermon der danach kommt ist mir schleierhaft.
Warum wird da so eine komplexe Abfrage generiert? Nicht dass ich jetzt ein SQL-Guru wäre...aber ich hätte einfach nach der ID-Angabe aufgehört.

Ach..und noch eine Frage...wie kann ich mir denn den UpdateCommand mit eingefügten Parametern anschauen? Das ist vielleicht für zukünfitige Debugs ganz hilfreich.

Vielen Dank!!

CC

J
3.331 Beiträge seit 2006
vor 14 Jahren

Das Binding beenden war der Schlüssel zum Erfolg!

Nachdem dieses Problem schon 100x festgestellt und beantwortet wurde, konnte ich mich daran erinnern und den Hinweis geben, auch wenn deine Problembeschreibung darauf nicht hingedeutet hat.

Ich habe mir den UpdateCommand (der vom CommandBuilder generiert wurde) ...
Bis zum WHERE ist mir alles klar...die ID versteht sich von selbst. Nur der Sermon der danach kommt ist mir schleierhaft.
Warum wird da so eine komplexe Abfrage generiert? Nicht dass ich jetzt ein SQL-Guru wäre...aber ich hätte einfach nach der ID-Angabe aufgehört.

Das ist der Unterschied zwischen einem Menschen und einem Automaten. Der Mensch denkt zuerst nach; der Automat bastelt alles zusammen, was als NULL und Leerstring denkbar ist. (Das ist einer der Gründe, warum typ.DataSet und TableAdapter solche Code-Monster erzeugen und teilweise abgelehnt werden.)

wie kann ich mir denn den UpdateCommand mit eingefügten Parametern anschauen?

Grundsätzlich gar nicht (vielleicht bei Access, aber bei einer richtigen Datenbank nicht). Das gehört zur Sicherheit bei den Parametern:

Der DB-Server übernimmt zuerst den Befehl selbst und bereitet ihn vor, dann fügt er die Parameter-Werte ein.

Der DB-Server macht das, nicht das NET-Programm. Siehe auch [Artikelserie] Parameter von SQL Befehlen

Jürgen

2.223 Beiträge seit 2005
vor 14 Jahren

Ein weiterer Grund, warum so ein SQL Monster generiert wird ist.

Änderungen die an diesem Datensatz, von einem anderen User gemacht wurden, sollen nicht einfach von dem Generierten SQL Command ins Nirvana geschossen werden.

Herzliche Grüße
Lars

C
CosmicCode Themenstarter:in
5 Beiträge seit 2009
vor 14 Jahren

Alles klar!
Super! Vielen Dank euch beiden!

5.299 Beiträge seit 2008
vor 14 Jahren

Das SqlMonster kann man auch abstellen, nämlich indem man CommandBuilder.ConflictOption.OverWriteChanges einstellt.
(Geht auch bei den mittm typ.Dataset mit-generierten TableAdaptern, ist aber ziemlich versteckt, iwo bei "Konfigurieren - Optionen".)

Die default-ConflictOption ist nämlich ConflictOption.QueryAllColumns, mit dem Ziel (wurde schon gesagt), mitzubekommen, ob in der Zwischenzeit ein anderer User denselben Datensatz auch geändert hat.

Dann hat man den sog. "DBConcurrency"-Konflikt, nämlich der andere findet das vlt. nicht gut, wenn seine Änderung ohne weiteres überschrieben wird.

Der frühe Apfel fängt den Wurm.

C
CosmicCode Themenstarter:in
5 Beiträge seit 2009
vor 14 Jahren

Hey ErfinderDesRades...danke für diesen Tip!
Ich bin eigentlich ein Freund des "händischen" Programmierens...bin daher von diesem ganzen Generiere garnicht so angetan...aber was ich unschlagbar finde ist das "reinziehen" von Feldern aus DataSets in Forms. Gibts da evtl. ne Möglichkeit auch mit händisch programmierte DataSets in den Drag and Drop Komfort zu kommen? Jedes Steuerelement per Hand zu programmieren ist mir echt zu umständlich...

5.299 Beiträge seit 2008
vor 14 Jahren

Dataset händisch gecodet - heißt das, für jede Tabelle, für jede Spalte, für jeden ValueTyp jeder Spalte, jede DataRelation schreibst du eine oder mehr Zeilen Code, und kannst am Ende doch nur mit Casts und String-Schlüsseln auf die Dinger zugreifen?

Äh, nein, da weißichnix, wie man sowas ins Datenfenster kriegt. Bei Dataset gibts m.E. keine Alternative zum Generieren, bzw. neu erstellen im Datasset-Designer.

Was die generierten Dateien so fett macht, sind v.a. die mit-generierten TableAdapter, und da gehe ich neuerdings dazu über, die gleich nachm Generieren wieder rauszuschmeissen, und meine DataAdapter auch "händisch", mit CommandBuildern zu konfigurieren.

Ohne TableAdapter sind typ.Datasets doch wirklich nurnoch schnuckelig, findeste nicht?
😉

Der frühe Apfel fängt den Wurm.

J
3.331 Beiträge seit 2006
vor 14 Jahren

Ohne TableAdapter sind typ.Datasets doch wirklich nurnoch schnuckelig, findeste nicht?

1 MB für die Designer.cs findest du schnuckelig? Naja... Jürgen

5.299 Beiträge seit 2008
vor 14 Jahren

Also ich hab hier eines mit 26 Tabellen, 23 DataRelations und insges. ca. 200 DataColumns.

Die Designer.vb hat 823KB, das findich für son Monstrum noch vertretbar.

Wie gesagt: generierte TableAdapter im DatasetDesigner rausschmeißen.

Der frühe Apfel fängt den Wurm.

J
3.331 Beiträge seit 2006
vor 14 Jahren

das findich für son Monstrum noch vertretbar.

Da stimme ich voll zu, aber "schnuckelig" ist etwas anderes. Jürgen

C
CosmicCode Themenstarter:in
5 Beiträge seit 2009
vor 14 Jahren

=) Dagegen ist mein Projekt ja wirklich schnuckelig. 5 Tabellen und ca. 40 Cols. Naja...also das ist jetzt mein ersten C# DB Projekt...und wenn man mal dahintergestiegen ist was diese ganzen Generierten Helferlein so alles machen und können will man sie garnichtmehr missen! Muss also meinen Post über "händisches Programmieren" teilweise revidieren 😁