Montag, 30. Januar 2012

Januar 2012 / C# AccessDB auf DataGridView Teil 2

Zugriff auf Access-DB mit C#

Zu diesem Thema habe ich bereits vor einigen Monaten im August 2011 einen Blogeintrag verfasst. In diesem Eintrag findet man die Anleitung, um eine Tabelle aus einer Access-Datenbank zu holen, und wieder zu speichern.

Falsche Daten abfangen
Sobald nun eine Verbindung zur Datenbank besteht, und mind. ein DataGridView mit einer Tabelle verbunden ist, sollte man die eingegebenen Daten überprüfen.
Gibt man nämlich in ein Feld, in welches nur Zahlen geschrieben werden sollten Buchstaben ein, so wird das DataError-Event ausgelöst.

Eine ziemlich einfache Lösung wäre z.B. bloss folgende Zeile einzufügen:
MessageBox.Show("Fehlerhafte Dateneingabe!");
So wird dem Benutzer, bei einer Falscheingabe mitgeteilt, dass er einen Fehler gemacht hat und er kann das Feld nicht verlassen, bis die eingegebenen Daten das korrekte Format haben.

Es gibt natürlich noch andere Möglichkeiten, auf dieses Event zu reagieren, aber ich denke es ist schon mal nicht schlecht.

ID eines neuen Datensatzes
Da die ID normalerweise von der Datenbank selbst generiert wird und sie im DataGridView, so hoffe ich zumindest, nicht angezeigt wird, fällt einem dieses Problem zuerst gar nicht wirklich auf.
Hier noch der Code um eine Spalte auszublenden:

DataGridView.Columns["Spaltenname"].Visible = false;

Das Problem ist, dass in der Datenbank zwar eine ID vorhanden ist, das DataGridView diese jedoch nicht eingetragen hat bzw. diese gar nicht kennt. Wenn also ein neuer Datensatz erstellt wird, dieser mit Update() in die Datenbank gespeichert wurde und der Benutzer anschliessend diesen Datensatz erneut bearbeiten & speichern möchte, wird eine Exception ausgegeben, da der Datensatz keine ID hat.
Um das zu verhindern, muss man die ID von der Datenbank holen.

Dazu muss man unsere Verbindung ein kleines bisschen umbauen:
Anstatt wie im anderen Blog-Eintrag angegeben den DataAdapter direkt mit dem Abfrage und dem Connecting-string(strConnect) zu instanziieren, wird zuerst eine Connection mit dem Connecting-string erstellt und der DataAdapter dann mit der Connection instanziiert:
Aus:

OleDbDataAdapter dAdapter = new OleDbDataAdapter(strAbfrage, strConnect); dAdapter = new OleDbDataAdapter(strAbfrage, strConnect);

wird also:

OleDbConnection dbConnection = new OleDbConnection(strConnect);
dbConnection.Open();
OleDbDataAdapter dAdapter = new OleDbDataAdapter(strAbfrage, dbConnection);

Das macht für die Verbindung nun eigentlich keinen wirklich grossen Unterschied, aber um das Problem zu beheben, muss eine Connection verwendet werden.

Jetzt muss in derselben Methode, in der Sie die Verbindung aufbauen, folgende Zeile eingefügt werden:

dAdapter.RowUpdated += new OleDbRowUpdatedEventHandler(dAdapter_RowUpdated);

Das fügt einen OleDbRowUpdatedEventHandler hinzu, was so viel heisst wie: wir können nun das RowUpdated-Event abfangen.
Wir erstellen also folgende Prozedur:

private void dAdapter_RowUpdated (object sender, OleDbRowUpdatedEventArgs e)
{
    if (e.StatementType == StatementType.Insert)
    {
        OleDbCommand cmdNewID = new OleDbCommand("SELECT @@IDENTITY", dbConnection);
        e.Row[idColumn] = (int) cmdNewID.ExecuteScalar();
    }
}

Hier wird also zuerst abgefragt, ob es sich um ein Insert-Statement handelt.
Wenn das Zutrifft, wird die ID in die Zelle im Datagridview geschrieben, wobei e das Datagridview und idColumn den Namen oder den Index der Spalte darstellt.
Problem gelöst.

Exeption bei Checkboxen Es kam vor, dass wenn ich wahllos auf den Checkboxen herumgedrückt habe, ich irgendwann eine Exception bekam. Ich fand heraus, dass es genau bei folgendem Vorgang stattfand:
Sobald ich einen neuen Datensatz erstellt und anschliessend, nachdem ich den Datensatz bereits gespeichert hatte, eine Checkbox gesetzt habe.

Der Grund dafür ist, dass die Datenbank automatisch alle Werte der nicht gesetzten Checkboxen als false speichert, was auch richtig ist. Das DataGridView hingegen, speichert den Wert dieser Checkboxen als null ab. Beim Speichern eines Datensatzes überprüft der DataAdapter immer, ob die aktuellen Daten in der Datenbank und die beim letzten Mal gelesenen bzw. gespeicherten Daten übereinstimmen.
Da die Datenbank nun überall false, das geholte DataTable jedoch überall null gespeichert hat, wird eine Exception ausgegeben.

Die Lösung dieses Problems ist es, im DefaulValuesNeeded-Event des DataGridViews alle null-Werte in bool-Zellen, also Checkboxen, auf false zu ändern.
Hier ein Teil meiner Methode:

for (int i = 0; i < dgv.Columns.Count; i++)
{
    if (dgv.SelectedCells[0].OwningRow.Cells[i].ValueType == typeof(Boolean) && dgv.SelectedCells[0].OwningRow.Cells[i].Value == null)
    {
        dgv.SelectedCells[0].OwningRow.Cells[i].Value = false;
    }
}

dgv repräsentiert hier das DataGridView.

Keine Kommentare:

Kommentar veröffentlichen