2009-07-28 17 views
100

Pro meiner anderen question here about Disposable objects, sollten wir Close() vor dem Ende eines Verwendungsblocks aufrufen?Muss ich eine SQLConnection schließen(), bevor sie entsorgt wird?

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(); 
} 

Antwort

96

Da Sie eine using-Block haben, die Dispose-Methode des SQLCommand wird aufgerufen, und es wird die Verbindung schließen:

// 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); 
} 
+1

Ist _this._poolGroup = null; _ bedeutet, dass die Verbindung nicht zum Verbindungspool zurückkehrt? also werde ich n-1 Verbindungen haben? –

1

Nein, erbt die Klasse von SqlConnection IDisposable, und wenn das Ende der Verwendung (für das Verbindungsobjekt) angetroffen wird, ruft es automatisch die Entsorgung auf der SqlConnection Klasse.

3

Nein, die Verwendung von Block ruft Dispose() für Sie auf, so dass Sie nicht Close() anrufen müssen.

+0

Sorry, sollte ich gesagt, dass für die meisten Objekte, die IDisposable und eine Close() Methode, ruft Close() Enden implementieren rufen Sie Dispose() sowieso hinter den Kulissen auf. –

+6

Ist das nicht umgekehrt - 'Dispose()' ruft 'Close()' auf, nicht umgekehrt? – Town

+1

Es ist beides, normalerweise. Aus irgendeinem Grund entschieden sie sich zu implementieren, dass Close auch Dispose aufrufen würde.Für eine SqlConnection ist dies keine große Sache, aber StreamWriters wird eine Ausnahme auslösen, wenn Sie sie schließen und dann disposieren. Meine Vermutung wäre, dass sie dieses Verhalten nicht ändern werden, nur weil es das ist, was die Leute jetzt erwarten. –

2

Nein, es ist nicht notwendig, eine Verbindung vor dem Aufruf von Dispose zu schließen.

Einige Objekte (wie SQLConnections) können nach Aufruf von Close wieder verwendet werden, aber nicht nach dem Aufruf von Dispose. Für andere Objekte, die Close aufrufen, ist das gleiche wie der Aufruf von Dispose. (Manual und Bäche Ich denke, verhalten sich wie diese)

20

Das Zerlegen von SqlConnection von .NET Reflector mit :

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

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

Er ruft Close() innerhalb von Dispose()

+1

@statisjason: Könnten Sie bitte sagen, dass, wie nutzen Sie den Vorteil der Verwendung von Disassembler-Linie. Net-Reflektor? – odiseh

+3

@odiseh herunterladen .NET Reflector, reflector.exe ausführen, und Sie können jede. NET-DLL (einschließlich der Standardbibliothek) öffnen. Es bietet Ihnen eine Baumstruktur, die dem Objekt-Browser von Visual Studio ähnelt. Sie können jedoch mit der rechten Maustaste auf eine Klasse oder Methode klicken und auf "disassemblieren" klicken. Die Quelle wird dann in C# oder VB an Sie zurückgesandt, je nachdem, was Sie ausgewählt haben Optionen. – statenjason

3

Mit Reflector, können Sie diese th sehen e Dispose Methode von SqlConnection tatsächlich ruft Close();

15

Das Schlüsselwort using wird die Verbindung korrekt schließen, sodass der zusätzliche Aufruf von Close nicht erforderlich ist.

Aus dem MSDN-Artikel auf SQL Server Connection Pooling:

„Wir empfehlen dringend, dass Sie immer die Verbindung zu schließen, wenn Sie fertig mit ihm sind, so dass die Verbindung wird den Pool zurückgegeben werden, können Sie. tue dies entweder über die schließen oder Entsorgen Methoden des Connection-Objekts, oder durch alle Verbindungen innerhalb einer using-Anweisung in C#“Öffnen

Die tatsächliche Implementierung von SqlConnection.Dispose .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); 
} 
+1

+1 für MSDN-Link - Ich mag Reflektor \ ILspy wie der nächste Typ, aber die Dokumente sind, wo ich gehen möchte, um meine Antworten zu finden. – mlhDev

Verwandte Themen