2011-04-06 19 views
15

Solución final:

La conexión se agregó al grupo de conexiones. Así que lo cerré, pero aún así permaneció físicamente abierto. Con el parámetro ConnectionString "Pooling = false" o los métodos estáticos MySqlConnection.ClearPool (conexión) y MySqlConnection.ClearAllPools se puede evitar el problema. Tenga en cuenta que el problema era que la conexión todavía estaba activa cuando cerré la aplicación. Aunque lo cerré. Entonces, o no uso la agrupación de conexiones o borro el grupo específico antes de cerrar la conexión y el problema está resuelto. Me tomaré mi tiempo para averiguar cuál es la mejor solución en mi caso.El uso de MySQLConnection en C# no se cierra correctamente

Gracias a todos los que respondieron! Me ayudó a comprender mejor los conceptos de C# y aprendí mucho de la información útil. :)

===

problema original:

He buscado desde hace un tiempo y no he encontrado la solución para mi problema: Soy nuevo en C# y trato de escribir una clase para facilitar las conexiones de MySql. Mi problema es, después de abrir una conexión y cerrarla. Todavía está abierto en la base de datos y se cancela.

Estoy usando la 'utilización' de la declaración 'por supuesto, pero la conexión sigue abierta y se cancela después de que salga del programa.

Esto es lo que se ve mi código como:

using (DatabaseManager db = new DatabaseManager()) 
{ 
using (MySqlDataReader result = db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC")) 
{ 
    foreach (MySqlDataReader result in db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC")) 
    { 
     //Do stuff here 
    } 
} 
} 

El gestor de base de datos de clase abre la conexión y la cierra cuando son desechados:

public DatabaseManager() 
{ 
    this.connectionString = new MySqlConnectionStringBuilder("Server=localhost;Database=businessplan;Uid=root;"); 
    connect(); 
} 
private bool connect() 
{ 
    bool returnValue = true; 
    connection = new MySqlConnection(connectionString.GetConnectionString(false)); 
    connection.Open(); 
} 

public void Dispose() 
{ 
    Dispose(true); 
} 

public void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     if (connection.State == System.Data.ConnectionState.Open) 
     { 
      connection.Close(); 
      connection.Dispose(); 
     } 
    } 
    //GC.SuppressFinalize(this);//Updated 
} 
//Updated 
//~DatabaseManager() 
//{ 
// Dispose(false); 
//} 

Por lo tanto, he comprobado en el depurador y el Desechar () -method se llama y se ejecuta correctamente. ¿Qué me estoy perdiendo? ¿Hay algo que hice mal o mal entendido?

¡Se agradece cualquier ayuda!

Saludos, Simon

PS: Por si acaso, el DataReader() - Método (Versión actualizada):

public IEnumerable<IDataReader> DataReader(String query) 
    { 
     using (MySqlCommand com = new MySqlCommand()) 
     { 
      com.Connection = connection; 
      com.CommandText = query; 
      using (MySqlDataReader result = com.ExecuteReader(System.Data.CommandBehavior.CloseConnection)) 
      { 
       while (result.Read()) 
       { 
        yield return (IDataReader)result; 
       } 
      } 
     } 
    } 

Ok, me trataron de usar el regreso rendimiento:

foreach (MySqlDataReader result in db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC")) 
{ 
    //... 
} 

Y cambié el método DataReader:

public IEnumerable<IDataReader> DataReader(String query) 
    { 
     using (MySqlCommand com = new MySqlCommand()) 
     { 
      com.Connection = connection; 
      com.CommandText = query; 
      using (MySqlDataReader result = com.ExecuteReader()) 
      { 
       while (result.Read()) 
       { 
        yield return (IDataReader)result; 
       } 
      } 
     } 
    } 

Funciona en la forma en que puedo recuperar los datos, sin embargo, todavía tengo el mismo problema: La conexión no se cierra correctamente. :(

+0

Como no tiene ningún recurso no administrado, no necesita un finalizador. – SLaks

+0

Eso es verdad. Pero no está doliendo actualmente, ¿no es así? Corrígeme si estoy equivocado. El objetivo principal es cerrar las conexiones no utilizadas tan pronto como ya no sean necesarias. Este patrón parecía ser una forma fácil de lograr este objetivo. Lo implementé tal como se mostró en muchos ejemplos en la web. Eventualmente lo cambiaré para deshacerme del código redundante. – Skalli

+1

Es un golpe de rendimiento, pero de lo contrario, no. – SLaks

Respuesta

15

Im seguro de MySqlConnection pero el contador de SQL Server parte utiliza agrupación de conexiones y no se cierra cuando se llama estrecha en vez de eso lo pone en la agrupación de conexiones!

Editar: ¡Asegúrese de disponer del objeto Reader, Command y Connection!

Editar: Resuelto con el "Pooling = false" ConnectionString de parámetros o el métodos MySqlConnection.ClearPool estática (conexión) y MySqlConnection.ClearAllPools()

+0

Actualmente estoy usando la directiva de uso para estos. Ver [enlace] (http://stackoverflow.com/questions/5567097/using-mysqlconnection-in-c-does-not-close-properly/5567722#5567722). Todavía no sirve de nada. – Skalli

+1

Esta publicación en realidad tenía la respuesta que estaba buscando, pero no la reconocí, porque no estaba familiarizado con el funcionamiento de Connection Pooling. Ahora entiendo y resolví el problema. Entonces, muchas gracias @Petoj. – Skalli

+0

no hay problema, feliz de ayudar! – Peter

5

Debe ajustar el Comando y el DataReader en las declaraciones using también.

+1

Bueno, pero ¿cómo? Si envuelvo el MySqlDataReader en un bloque de uso, solo está disponible localmente. El método DataReader devuelve el objeto a un bloque que usa. Supongo que esto eliminaría el MySqlDataReader-Object al final del bloque de uso: using (MySqlDataReader result = db.DataReader (...) – Skalli

+0

No podrá ajustar eso porque está devolviendo MySqlDataReader - No creo que deba deshacerse de MySqlCommand hasta que haya terminado con MySqlDataReader. Probablemente debería buscar un retorno de rendimiento para convertir esto en un cierre. –

+0

Tiene razón. Podría manejar el evento 'Disposed' del lector: 'reader.Disposed + = delegate {com.Dispose();}' – SLaks

-1

Tenga una mirada en el uso de algo como esto:

private static IEnumerable<IDataRecord> SqlRetrieve(
    string ConnectionString, 
    string StoredProcName, 
    Action<SqlCommand> AddParameters) 
{ 
    using (var cn = new SqlConnection(ConnectionString)) 
    using (var cmd = new SqlCommand(StoredProcName, cn)) 
    { 
     cn.Open(); 
     cmd.CommandType = CommandType.StoredProcedure; 

     if (AddParameters != null) 
     { 
      AddParameters(cmd); 
     } 

     using (var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) 
     { 
      while (rdr.Read()) 
       yield return rdr; 
     } 
    } 
} 
+0

Voy a echarle un vistazo. Parece bastante interesante. No he visto un rendimiento antes. – Skalli

+0

@ user694856 http://stackoverflow.com/ questions/850065/return-datareader-from-datalayer-in-using-statement –

+0

He intentado usarlo, ver mi publicación: [link] (http://stackoverflow.com/questions/5567097/using-mysqlconnection-in- c-does-not-close-properly/5567722 # 5567722) – Skalli

2

De acuerdo con los documentos de MySQL, el MySqlConnection no está cerrada cuando se va fuera del ámbito. Por lo tanto, no debes usarlo dentro de un uso.

Cita ... "Si MySqlConnection se sale del alcance, no se cierra. Por lo tanto, debe cerrar la conexión explícitamente llamando a MySqlConnection.Close o MySqlConnection.Dispose".

+2

El uso debe llamar cerca y deshacerse cuando el objeto se sale del alcance. Es lo mismo que usar un bloque try catch y cerrarlo y disponerlo en el bloque finally. – Skalli

+1

@Skalli es correcto. Salir del alcance de una sentencia using no es lo mismo que perder el alcance en un sentido del lenguaje. Una instrucción using llamará a Close. –

Cuestiones relacionadas