2011-01-03 6 views
1

Ich habe eine Anwendung, die einen mysql-Befehl (Abfrage) "show databases" feuert, die Abfrage funktioniert und gibt ordnungsgemäß zurück, aber ich kann meine Verbindungen nicht schließen. Der Benutzer, den ich benutzte, hatte 24 Verbindungen gleichzeitig erlaubt, so dass das Problem weiter unten in meinem Programm auftauchte, aber das Reduzieren der erlaubten Verbindungen auf 2 zeigt mir, dass ich nicht einmal die erste Abfrage schließen kann (die nicht in einer Schleife ist). Der Code ist der folgende:C# MySqlConnection wird nicht geschlossen

protected override Dictionary<string, Jerow_class_generator.Database> loadDatabases() 
    { 
     MySqlConnection sqlCon = new MySqlConnection(this.ConnectionString); 
     sqlCon.Open(); 

     MySqlCommand sqlCom = new MySqlCommand(); 
     sqlCom.Connection = sqlCon; 
     sqlCom.CommandType = CommandType.Text; 
     sqlCom.CommandText = "show databases;"; 

     MySqlDataReader sqlDR; 
     sqlDR = sqlCom.ExecuteReader(); 

     Dictionary<string, Jerow_class_generator.Database> databases = new Dictionary<string, Jerow_class_generator.Database>(); 
     string[] systemDatabases = new string[] { "information_schema", "mysql" }; 

     while (sqlDR.Read()) 
     { 
      string dbName = sqlDR.GetString(0); 
      if (!systemDatabases.Contains(dbName)) 
      { 
       databases.Add(sqlDR.GetString(0), new MySQL.Database(dbName, this)); 
      } 
     } 

     sqlCom.Dispose(); 
     sqlDR.Close(); 

     sqlCon.Close(); 
     sqlCon.Dispose(); 
     return databases; 
    } 

P.S. Die 'Neue MySQL.Datenbank (dbName, this));' ist mein owm gemacht Klasse, die nur die DB-Struktur speichert, könnte als irrelevant betrachtet werden.

Der genaue Fehler, den ich bekomme, ist 'max_user_connections'. in der connection.open-Zeile des nächsten Mal, wenn eine Abfrage ausgelöst werden muss.

Antwort

6

Anstatt die Verfolgung aller Open/Close/Dispose alle über den Ort nennt, würde ich empfehlen, nur all jene mit using statements ersetzen. Dies stellt sicher, dass der erwartete Umfang jedes Objekts klar ist und dass es beim Verlassen dieses Bereichs zerstört/entsorgt wird.

+0

Danke für die Anregung sieht, mehr sauberer. Aber immer noch kein Ergebnis. –

+0

@Daniel, für MySQL ist es immer noch am besten, die Verbindung manuell zu schließen, diese Verbindung früher zu schließen, bevor C# GC tut. – Adrian

0

Wenn Sie "using" Schlüsselwort verwenden, was geschehen ist. Wenn der Garbage Collector es aktiviert, entsorgen Sie zuerst Objekte, die mit Anweisung dekliniert wurden.

0

Ich empfehle Verbindungspooling in Kombination mit der MySqlHelper-Klasse, die Verbindungszeichenfolge als erstes Argument übergeben. Dadurch kann MySQL die Verbindung bei Bedarf öffnen oder gemäß dem Pooling-cfg offen halten, ohne dass Sie etwas darüber wissen müssen.

+0

Ich habe dies angewendet, um Verbindungszeichenfolgen für den MySQL-Helfer bereitzustellen, aber immer noch nichts. Ich werde versuchen, jetzt 1 Verbindungsobjekt wiederzuverwenden –

0

Ich habe meinen Code geändert, um 1 Verbindung zu verwenden und offen zu halten, und beim Testen stieß ich auf einen Fehler, dass ein Datenreader geschlossen werden sollte. Nun, da alle meine Abfragen das DataReader-Objekt nicht geschlossen haben (ich habe dataTable.Load (cmd.ExecuteReader()) verwendet). Ich denke, das Problem könnte da sein.

Keeping 1 offene Verbindung funktionierte perfekt, so dass ich nicht weiß, was das nicht schließen Problem verursacht. Ich glaube es war der DataReader, der sich nicht selbst schließt.

1

Zusammen mit den using oben genannten Vorschlägen, wenn Ihre sqlDR Variable Erstellung sollten Sie das CloseConnection Befehl Verhalten verwenden, um die tatsächliche Verbindung zu schließen, wenn die Ihre beabsichtigte Aktion. Wie in der Dokumentation here erwähnt.

When the command is executed, the associated Connection object is closed when the associated DataReader object is closed.

So Ihr Code Ihre Leser instanziiert würde wie folgt aussehen:

//to instantiate your variable 
    MySqlDataReader sqlDR; 
    sqlDR = sqlCom.ExecuteReader(CommandBehavior.CloseConnection); 

    //closing your datareader reference here will close the connection as well 
    sqlDR.Close(); 

Wenn Sie den gesamten Code in einem using Block unter Verwendung der obigen Verfahren wickeln, Sie brauchen nicht von diese Close() oder Dispose() andere Methoden als die sqlDR.Close();

2

Close() noch using allein mit Ihrem Problem bec helfen ADO.NET verwendet ein eigenes Verbindungspooling und Verbindungen werden standardmäßig nicht geschlossen, bis das Programm geschlossen wird. Es gibt wenige Optionen, um dies zu lösen, aber berücksichtigen Sie die Auswirkungen auf die Leistung und ist das wirklich gewünschte Verhalten für Ihre Anwendung.

Für weitere Informationen lesen: SQL Server Connection Pooling (ADO.NET)

Verwandte Themen