web-dev-qa-db-fra.com

Est-il nécessaire de fermer et de supprimer manuellement SqlDataReader?

Je travaille avec du code hérité ici et il existe de nombreuses instances de SqlDataReader qui ne sont jamais fermées ou supprimées. La connexion est fermée mais, je ne sais pas s'il est nécessaire de gérer le lecteur manuellement.

Cela pourrait-il entraîner un ralentissement des performances?

83
Jon Ownbey

Essayez d'éviter d'utiliser des lecteurs comme celui-ci:

SqlConnection connection = new SqlConnection("connection string");
SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection);
SqlDataReader reader = cmd.ExecuteReader();
connection.Open();
if (reader != null)
{
      while (reader.Read())
      {
              //do something
      }
}
reader.Close(); // <- too easy to forget
reader.Dispose(); // <- too easy to forget
connection.Close(); // <- too easy to forget

Au lieu de cela, enveloppez-les dans des instructions:

using(SqlConnection connection = new SqlConnection("connection string"))
{

    connection.Open();

    using(SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            if (reader != null)
            {
                while (reader.Read())
                {
                    //do something
                }
            }
        } // reader closed and disposed up here

    } // command disposed here

} //connection closed and disposed here

La déclaration d'utilisation garantira l'élimination correcte de l'objet et la libération des ressources.

Si vous oubliez, vous laissez le nettoyage au dépotoir, ce qui peut prendre un certain temps.

116
Codebrain

Notez que la suppression d'un SqlDataReader instancié à l'aide de SqlCommand.ExecuteReader () --- not ferme/supprime la connexion sous-jacente.

Il existe deux modèles communs. Dans le premier, le lecteur est ouvert et fermé dans le cadre de la connexion:

using(SqlConnection connection = ...)
{
    connection.Open();
    ...
    using(SqlCommand command = ...)
    {
        using(SqlDataReader reader = command.ExecuteReader())
        {
            ... do your stuff ...
        } // reader is closed/disposed here
    } // command is closed/disposed here
} // connection is closed/disposed here

Parfois, il est pratique qu'une méthode d'accès aux données ouvre une connexion et renvoie un lecteur. Dans ce cas, il est important que le lecteur renvoyé soit ouvert à l'aide de CommandBehavior.CloseConnection, afin que la fermeture/suppression du lecteur ferme la connexion sous-jacente. Le motif ressemble à ceci:

public SqlDataReader ExecuteReader(string commandText)
{
    SqlConnection connection = new SqlConnection(...);
    try
    {
        connection.Open();
        using(SqlCommand command = new SqlCommand(commandText, connection))
        {
            return command.ExecuteReader(CommandBehavior.CloseConnection);
        }
    }
    catch
    {
        // Close connection before rethrowing
        connection.Close();
        throw;
    }
}

et le code appelant a juste besoin de disposer ainsi le lecteur:

using(SqlDataReader reader = ExecuteReader(...))
{
    ... do your stuff ...
} // reader and connection are closed here.
49
Joe

Pour être sûr, encapsulez chaque objet SqlDataReader dans un en utilisant l'instruction .

10
Kon

Enveloppez simplement votre SQLDataReader avec l'instruction "using". Cela devrait prendre en charge la plupart de vos problèmes.

5
J.W.