none
OleDbConnection: Diesem Command ist bereits ein geöffneter DataReader zugeordnet, der zuerst geschlossen werden muss. RRS feed

  • Frage

  • Hallo!

    Ich möchte auf eine lokale Access-Datenbank mit einer OleDbConnection zugreifen.

    Ich verstehe nicht, warum immer wieder die Fehlermeldung: "Diesem Command ist bereits ein geöffneter DataReader zugeordnet, der zuerst geschlossen werden muss." erscheint, da ich nur einmal in meinem Programm die Verbindung aufbaue und auch wieder schließe.

    Hier der Code:

    int anz; OleDbConnection con1 = new OleDbConnection( //Verbindung zur Access-Datenbank initialisieren @"Provider=Microsoft.JET.OLEDB.4.0; Data Source=C:\Datenbank.mdb"); //Connection String try { con1.Open(); //Verbindung zur Datenbank aufnehmen OleDbCommand cmd1 = new OleDbCommand("SELECT COUNT(*) FROM Bild", con1); OleDbDataReader dr1 = cmd1.ExecuteReader(); String result = cmd1.ExecuteScalar().ToString();

    anz = Convert.ToInt32(result); dr1.Close(); cmd1.Dispose(); con1.Close(); } catch (Exception err) //Abfangen von Fehlern { MessageBox.Show(err.Message); //Ausgabe der Fehlermeldung }

    Wo liegt hier das Problem?

    Vielen Dank schonmal für die Hilfe!


    Montag, 7. Juli 2014 09:15

Antworten

  • Hallo,

    kleine Ergänzung:

    Anstatt Dispose getrennt aufzurufen, solltest Du besser auf die using Anweisung setzen. Denn auch mit Stefans Korrektur ist es möglich, dass Du am Ende mit einer offenen Verbindung da stehst. Das  Ganze in eine Methode verpackt:

            public static int GetBildAnzahl()
            {
                try
                {
                    using (var connection = new System.Data.OleDb.OleDbConnection(@"Provider=Microsoft.JET.OLEDB.4.0; Data Source=C:\Datenbank.mdb"))
                    {
                        connection.Open();
                        using (var command = new System.Data.OleDb.OleDbCommand("SELECT COUNT(*) FROM Bild", connection))
                        {
                            return (int)command.ExecuteScalar();
                        }
                    }
                }
                catch (System.Data.OleDb.OleDbException ex)
                {
                    MessageBox.Show("GetBildAnzahl: " + ex.Message);
                    return -1;
                }
            }

    (wobei ich das MessageBox.Show i. a. weglassen würde, da wäre eine Protokollierung sinnvoller).

    Da COUNT() immer einen Wert liefert reicht ein Cast auf int, ToString/ToInt32 macht nur unnötigen Unfug.

    Gruß Elmar

    Montag, 7. Juli 2014 12:06
    Beantworter

Alle Antworten

  • Hi,

    nuja, Du öffnest den DataReader, verwendest den aber nicht. Bevor Du dr1 wieder schließt, rufst Du cmd1.ExecuteScalar() auf. Zu dem Zeitpunkt ist der DataReader noch geöffnet.

    Probiers mal so:

    int anz;
    
    OleDbConnection con1 = new OleDbConnection( //Verbindung zur Access-Datenbank initialisieren
                               @"Provider=Microsoft.JET.OLEDB.4.0;
                               Data Source=C:\Datenbank.mdb" ); //Connection String
                                   
    try
    {
        con1.Open(); //Verbindung zur Datenbank aufnehmen
        OleDbCommand cmd1 = new OleDbCommand("SELECT COUNT(*) FROM Bild", con1);
        String result = cmd1.ExecuteScalar().ToString();
    
        anz = Convert.ToInt32(result);
    
        cmd1.Dispose();
        con1.Close();
        con1.Dispose();
    }
    catch (Exception err)               //Abfangen von Fehlern
    {
        MessageBox.Show(err.Message);   //Ausgabe der Fehlermeldung
    }
    


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Montag, 7. Juli 2014 09:43
    Moderator
  • Oh ja... Ist mir gar nicht aufgefallen -.-

    Jetzt funktionierts, vielen Dank! :)

    Montag, 7. Juli 2014 10:21
  • Hallo,

    kleine Ergänzung:

    Anstatt Dispose getrennt aufzurufen, solltest Du besser auf die using Anweisung setzen. Denn auch mit Stefans Korrektur ist es möglich, dass Du am Ende mit einer offenen Verbindung da stehst. Das  Ganze in eine Methode verpackt:

            public static int GetBildAnzahl()
            {
                try
                {
                    using (var connection = new System.Data.OleDb.OleDbConnection(@"Provider=Microsoft.JET.OLEDB.4.0; Data Source=C:\Datenbank.mdb"))
                    {
                        connection.Open();
                        using (var command = new System.Data.OleDb.OleDbCommand("SELECT COUNT(*) FROM Bild", connection))
                        {
                            return (int)command.ExecuteScalar();
                        }
                    }
                }
                catch (System.Data.OleDb.OleDbException ex)
                {
                    MessageBox.Show("GetBildAnzahl: " + ex.Message);
                    return -1;
                }
            }

    (wobei ich das MessageBox.Show i. a. weglassen würde, da wäre eine Protokollierung sinnvoller).

    Da COUNT() immer einen Wert liefert reicht ein Cast auf int, ToString/ToInt32 macht nur unnötigen Unfug.

    Gruß Elmar

    Montag, 7. Juli 2014 12:06
    Beantworter
  • Vielen Dank! Hab das abgeändert... jetzt steh ich leider vor dem nächsten Problem.

    Ich möchte Bilder über den Programmcode in mein Fenster einfügen, da der Dateipfad variabel ist und bekomme als Fehlermeldung in der Messagebox den Dateipfad des Bildes angezeigt. Stimmt etwas mit der Pfadzusammensetzung nicht?

    Hier der Code:

    try
                {
                    using (var connection = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Datenbank.mdb"))
                    {
                        connection.Open();
                        using (var command = new OleDbCommand("SELECT * FROM Grafik WHERE BildID = @idBilder", connection))
                        {
                            command.Parameters.AddWithValue("@idBilder", idBilder);
                            OleDbDataReader dr = command.ExecuteReader();
                            while (dr.Read())
                            {
                                String Pfad = (dr["Dateipfad"].ToString()) + "\\" + (dr["GrafikName"].ToString() + "." + (dr["Grafiktyp"].ToString()));
                                PictureBox Bildbox = new PictureBox();
                                Bildbox.Image = Image.FromFile(Pfad);
                                Bildbox.Width = Convert.ToInt32(dr["Breite"]);
                                Bildbox.Height = Convert.ToInt32(dr["Höhe"]);
                                Bildbox.Top = Convert.ToInt32(dr["yPos"]);
                                Bildbox.Left = Convert.ToInt32(dr["xPos"]);
                                this.BringToFront();
                                this.Controls.Add(Bildbox);
                                this.Visible = true; 
                            }
    
                        }
                    }
                }
                catch (Exception err)
                {
                    MessageBox.Show("Error: "+err.Message);
                }
    Danke!
    Dienstag, 8. Juli 2014 06:34
  • Hi,
    lass Dir mal den Inhalt der Variablen "Pfad" anzeigen. Vermutlich ist der Pfad falsch oder es gibt ihn nicht. Für das "Zusammenbasteln" von Pfadangaben ist die Nutzung der Path-Klasse ein besserer Weg. Nach dem Erzeugen des Pfades sollte noch ein File.Exists eingebaut werden, um wirklich sicher zu gehen, dass die Datei noch existiert.

    --
    Peter

    Dienstag, 8. Juli 2014 07:03
  • Hi, Danke,

    habe gerade die Path-Mehode ausprobiert und der Pfad wird in der Fehlermeldung auch richtig angezeigt... nur leider kein Bild...

     PictureBox Bildbox = new PictureBox();
                                Bildbox.Image = Image.FromFile(Path.Combine((dr["Dateipfad"].ToString()), (dr["GrafikName"].ToString()+"."+dr["Grafiktyp"].ToString())));

    Dienstag, 8. Juli 2014 07:06