Muss ich eine SQLConnection schließen (), bevor sie entsorgt wird?

113

Sollten wir gemäß meiner anderen Frage zu Einwegobjekten Close () vor dem Ende eines using-Blocks aufrufen?

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
quelle

Antworten:

107

Da Sie einen using-Block haben, wird die Dispose-Methode des SQLCommand aufgerufen und die Verbindung geschlossen:

// 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
quelle
1
Ist dies._poolGroup = null; bedeutet, dass die Verbindung nicht zum Verbindungspool zurückkehrt? Also werde ich n-1 Verbindungen haben?
Royi Namir
25

Demontage von SqlConnection mit .NET Reflector :

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

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

Es ruft Close () innerhalb von Dispose () auf

statenjason
quelle
1
@statenjason: Könnten Sie bitte sagen, wie Sie die Verwendung des .net-Reflektors für Disassembler nutzen können?
Odiseh
3
@odiseh Laden Sie einfach .NET Reflector herunter, führen Siereflector.exe aus, und Sie können jede .net-DLL (einschließlich der Standardbibliothek) öffnen. Sie erhalten eine Baumstruktur, die dem Objektbrowser von Visual Studio ähnelt. Sie können jedoch mit der rechten Maustaste auf eine beliebige Klasse oder Methode klicken und auf "Zerlegen" klicken. Anschließend wird die Quelle in C # oder VB an Sie zurückgegeben, je nachdem, was Sie in der Liste ausgewählt haben Optionen.
Statenjason
20

Das Schlüsselwort using schließt die Verbindung korrekt, sodass kein zusätzlicher Aufruf zum Schließen erforderlich ist.

Aus dem MSDN-Artikel zum SQL Server-Verbindungspooling :

"Wir empfehlen dringend, dass Sie die Verbindung immer schließen, wenn Sie sie nicht mehr verwenden, damit die Verbindung wieder in den Pool zurückgeführt wird. Sie können dies entweder mit den Methoden Schließen oder Entsorgen des Verbindungsobjekts oder durch Öffnen aller Verbindungen in a tun using-Anweisung in C # "

Die tatsächliche Implementierung von SqlConnection.Dispose mit .NET Reflector ist wie folgt:

// 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
quelle
1
+1 für MSDN-Link - Ich mag Reflector \ ILspy wie der nächste Typ, aber in den Dokumenten möchte ich meine Antworten finden.
mlhDev
5

Mit Reflector können Sie sehen, dass die DisposeMethode von SqlConnectiontatsächlich aufruft 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
quelle
3

Nein, der Using-Block ruft Dispose()sowieso für Sie auf, sodass Sie nicht anrufen müssen Close().

Jason Evans
quelle
Entschuldigung, ich hätte sagen sollen, dass für die meisten Objekte, die IDisposable implementieren und eine Close () -Methode haben, der Aufruf von Close () ohnehin Dispose () hinter den Kulissen für Sie aufruft.
Jason Evans
6
Ist das nicht umgekehrt - Dispose()Anrufe Close(), nicht umgekehrt?
Stadt
1
Normalerweise ist es beides. Aus irgendeinem Grund beschlossen sie zu implementieren, dass Close auch Dispose aufrufen würde. Für eine SqlConnection ist dies keine große Sache, aber StreamWriters lösen eine Ausnahme aus, wenn Sie sie schließen und dann entsorgen. Ich vermute, sie werden dieses Verhalten nicht ändern, nur weil es das ist, was die Leute jetzt erwarten.
2

Nein, es ist nicht erforderlich, eine Verbindung zu schließen, bevor Sie Dispose aufrufen.

Einige Objekte (wie SQLConnections) können nach dem Aufruf von Close wiederverwendet werden, jedoch nicht nach dem Aufruf von Dispose. Für andere Objekte entspricht der Aufruf von Close dem Aufruf von Dispose. (ManualResetEvent und Streams verhalten sich meiner Meinung nach so)

pipTheGeek
quelle
1

Nein, die SqlConnection-Klasse erbt von IDisposable. Wenn das Ende der Verwendung (für das Verbindungsobjekt) erreicht ist, ruft sie automatisch Dispose für die SqlConnection-Klasse auf.

blparker
quelle