Laden...

[MySQL 5] Update Methode schließt Reader nicht.

Erstellt von chea77er vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.248 Views
C
chea77er Themenstarter:in
74 Beiträge seit 2008
vor 13 Jahren
[MySQL 5] Update Methode schließt Reader nicht.

verwendetes Datenbanksystem: MySQL 5

Naja hier erstmal die Funktion um die es geht:

        public static void Update(DataTable ta, string table)
        {
            MySqlDataAdapter adapt = new MySqlDataAdapter("UPDATE " + table, connection);
            adapt.UpdateCommand = new MySqlCommand("UPDATE " + table, connection);
            adapt.Update(ta);
        }

Diese Funktion wird 4x hintereinander aufgerufen. Pro DB eben. (alle paar Minuten)
Beim ersten mal aufrufen gibt es keine probleme. Sobald es zum 2. mal ausgeführt wird. Gibt es folgende exception:

There is already an open DataReader associated with this Connection which must be closed first.

Mir ist bewusst das man einen DataReader schließen muss mit Close(). Nur ich benutze keinen. Kann es sein das die Update Methode von MySqlDataAdapter einen benutzt, und diesen aus irgenteinen Grund nicht mehr schließt.

Desweiteren stimmt das überhaupt so mit dem UpdateCommand?

Auserdem ist mir grad noch aufgefallen das es nur bei Tabellen geschieht wo es auch Änderungen gab.

J
3.331 Beiträge seit 2006
vor 13 Jahren

Kann es sein das die Update Methode von MySqlDataAdapter einen benutzt, und diesen aus irgenteinen Grund nicht mehr schließt.

Es ist denkbar, weil der DbDataAdapter auch den Erfolg des Speichern prüft. Das könntest du über den .NET Reflector kontrollieren.

Desweiteren stimmt das überhaupt so mit dem UpdateCommand?

Nein. Wenn du den UPDATE-Befehl manuell zuweist, muss er genau dem SQL-Befehl entsprechen, also mit SET, den Spalten und den Werten (natürlich als Parameter). Einfacher ist es, einen SELECT zuzuweisen; dann kann der DbDataAdapter sich die Speichern-Befehle in der Regel selbst erstellen (sofern der SELECT die Voraussetzungen erfüllt: kein JOIN, mit PrimaryKey).

Auserdem ist mir grad noch aufgefallen das es nur bei Tabellen geschieht wo es auch Änderungen gab.

Natürlich, so arbeitet die Update-Methode des DbDataAdapter, wie in :rtfm: beschrieben wird.

Alles zusammen ist das ein Grund mehr, sowohl DbConnection als auch DbDataAdapter in einem using-Block zu kapseln.

Gruß Jürgen

C
chea77er Themenstarter:in
74 Beiträge seit 2008
vor 13 Jahren

Nein. Wenn du den UPDATE-Befehl manuell zuweist, muss er genau dem SQL-Befehl entsprechen, also mit SET, den Spalten und den Werten (natürlich als Parameter). Einfacher ist es, einen SELECT zuzuweisen; dann kann der DbDataAdapter sich die Speichern-Befehle in der Regel selbst erstellen (sofern der SELECT die Voraussetzungen erfüllt: kein JOIN, mit PrimaryKey).

So habe nun folgendes probiert.

 MySqlDataAdapter adapt = new MySqlDataAdapter();
            adapt.SelectCommand = new MySqlCommand("SELECT * FROM " + table, connection);
            adapt.Update(ta);

Jedoch bekomm ich folgende Exception:

Für ein Update ist ein gültiger UpdateCommand erforderlich, wenn eine DataRow-Auflistung mit modifizierten Zeilen weitergegeben wird.

Ist schließlich verständlich, jedoch kann ich ja kein UPDATE Command eingeben dies soll sich ja schließlich vom DataTable generieren.

Zum Anderen Problem:
Wie kann ich dies nun fixxen, muss ich dann doch zu kompletten eigenen Befehelen zurück greifen. Ich möchte den anderen Programmieren möglichst so bieten, dass sie keine SQL Befehle nutzen sollen, sondern nur die Daten im DataTable ändern, und der rest soll sich von alleine dann speichern.
Ich

F
10.010 Beiträge seit 2004
vor 13 Jahren

Vielleicht solltest Du einfach mal die Grundlagen zum DataAdapter erlesen, die stehen sogar in Einsteigerbüchern.

http://openbook.galileocomputing.de/visual_csharp/visual_csharp_29_001.htm

3.825 Beiträge seit 2006
vor 13 Jahren

Hallo Chea,

hier ein Beispiel für das Ändern von Daten (auch mit MySQL getestet) :

http://www.seven-c.de/files/datenbankenhowto.htm Kapitel 6 und 9

Für MySQL 'Sql' gegen 'MySql' tauschen.

Ich benutze immer con.Open und conn.Close, obwohl das eigentlich nicht notwendig ist.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

C
chea77er Themenstarter:in
74 Beiträge seit 2008
vor 13 Jahren

Hallo BerndFfm,

Ich werde es mir gleich durchlesen. Vorher muss ich jedoch noch etwas hinzufügen.

Die Methode Fill von dem Adapter wird vorher ebenfalls aufgerufen. Und direkt die erste Tabelle mit änderungen schmeißt eine Exception.

Also schließt die Methode Fill den Reader wohl nicht.

EDIT:
So bin nun mal mit Reflector über die Fill Methode gegangen:

        try
        {
            QuietOpen(connection, out open);
            behavior |= CommandBehavior.SequentialAccess;
            using (IDataReader reader = null)
            {
                reader = command.ExecuteReader(behavior);
                if (datatables != null)
                {
                    return this.Fill(datatables, reader, startRecord, maxRecords);
                }
                return this.Fill(dataset, srcTable, reader, startRecord, maxRecords);
            }
        }
        finally
        {
            QuietClose(connection, open);
        }

Der Reader wird mit ExecuteReader geöffnet. Jedoch nie geschlossen. QuietClose() schließt die gesammte Connection mit .Close(). In this.Fill() konnte ich auch kein reader.Close() finden.

3.825 Beiträge seit 2006
vor 13 Jahren

Mit 'return' verlässt Du dein 'Fill', Close wird nie aufgerufen.

Für das Füllen eines Dataset benötigst Du in der Regel keinen DataReader, siehe mein Beispiel.

MS SQL erlaubt mehrere aktive DataReader, MySQL nur einen. Bei MS SQL wäre Dein Fehler nicht aufgefallen 😉
Ausser dass Dein Programm immer mehr Speicher braucht.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3