Dois-je fermer () un SQLConnection avant qu'il ne soit supprimé?

113

Par mon autre question ici sur les objets jetables , devrions-nous appeler Close () avant la fin d'un bloc using?

using (SqlConnection connection = new SqlConnection())
using (SqlCommand command = new SqlCommand())
{
    command.CommandText = "INSERT INTO YourMom (Amount) VALUES (1)";
    command.CommandType = System.Data.CommandType.Text;

    connection.Open();
    command.ExecuteNonQuery();

    // Is this call necessary?
    connection.Close();
}
John Bubriski
la source

Réponses:

107

Puisque vous avez un bloc using, la méthode Dispose de la SQLCommand sera appelée et fermera la connexion:

// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
CMS
la source
1
Fait ceci._poolGroup = null; signifie que la connexion ne revient pas au pool de connexions? alors j'aurai des connexions n-1?
Royi Namir
25

Désassemblage de SqlConnection de l'utilisation de .NET Reflector :

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }

    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

Il appelle Close () à l'intérieur de Dispose ()

statenjason
la source
1
@statenjason: pourriez-vous s'il vous plaît dire que comment profiter de l'utilisation de la ligne de désassembleurs .net réflecteur?
odiseh
3
@odiseh téléchargez simplement .NET Reflector, exécutez reflector.exe et vous pouvez ouvrir n'importe quelle DLL .net (y compris la bibliothèque standard). Il vous fournit une arborescence similaire au navigateur d'objets de Visual Studio, cependant, vous pouvez cliquer avec le bouton droit sur n'importe quelle classe ou méthode et cliquer sur "désassembler", il vous renverra ensuite la source en C # ou VB, selon ce que vous avez sélectionné dans le options.
statenjason
20

Le mot-clé using fermera la connexion correctement afin que l'appel supplémentaire à Close ne soit pas nécessaire.

De l'article MSDN sur le pool de connexions SQL Server :

"Nous vous recommandons vivement de toujours fermer la connexion lorsque vous avez fini de l'utiliser afin que la connexion soit renvoyée au pool. Vous pouvez le faire en utilisant les méthodes Close ou Dispose de l'objet Connection, ou en ouvrant toutes les connexions à l'intérieur d'un utilisation de l'instruction en C # "

L'implémentation réelle de SqlConnection.Dispose à l'aide de .NET Reflector est la suivante:

// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
Thomas Bratt
la source
1
+1 pour le lien MSDN - J'aime le réflecteur \ ILspy comme le prochain, mais les documents sont là où je voudrais aller pour trouver mes réponses.
mlhDev
5

En utilisant Reflector , vous pouvez voir que la Disposeméthode de SqlConnectionappelle réellement Close();

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
Aaron Daniels
la source
3

Non, le blocage Utilisation des appels Dispose()pour vous de toute façon, il n'est donc pas nécessaire d'appeler Close().

Jason Evans
la source
Désolé, j'aurais dû dire que pour la plupart des objets qui implémentent IDisposable et ont une méthode Close (), appeler Close () finit par appeler Dispose () dans les coulisses pour vous de toute façon.
Jason Evans
6
N'est-ce pas l'inverse - les Dispose()appels Close(), pas l'inverse?
Ville du
1
C'est les deux, généralement. Pour une raison quelconque, ils ont décidé d'implémenter que Close appellerait également Dispose. Pour un SqlConnection, ce n'est pas un gros problème, mais StreamWriters lèvera une exception si vous les fermez puis les supprimez. Je suppose qu'ils ne changeront pas ce comportement simplement parce que c'est ce à quoi les gens s'attendent maintenant.
2

Non, il n'est pas nécessaire de fermer une connexion avant d'appeler Dispose.

Certains objets (comme SQLConnections) peuvent être réutilisés après l'appel de Close, mais pas après l'appel de Dispose. Pour les autres objets, appeler Close équivaut à appeler Dispose. (ManualResetEvent et Streams, je pense, se comportent comme ça)

pipTheGeek
la source
1

Non, la classe SqlConnection hérite de IDisposable, et lorsque la fin de l'utilisation (pour l'objet de connexion) est rencontrée, elle appelle automatiquement la classe Dispose sur la classe SqlConnection.

Blparker
la source