Devo Close () una connessione SQLC prima che venga eliminata?


113

Per la mia altra domanda qui sugli oggetti usa e getta , dovremmo chiamare Close () prima della fine di un blocco 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();
}

Risposte:


107

Poiché hai un blocco using, verrà chiamato il metodo Dispose di SQLCommand e chiuderà la connessione:

// 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
Fa this._poolGroup = null; significa che la connessione non sta tornando al pool di connessioni? quindi avrò connessioni n-1?
Royi Namir

25

Disassemblaggio di SqlConnection dall'utilizzo di .NET Reflector :

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

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

Chiama Close () all'interno di Dispose ()


1
@statenjason: potresti per favore dire che come si approfitta dell'utilizzo di disassemblatori linea .net riflettore?
odiseh

3
@odiseh scarica semplicemente .NET Reflector, esegui reflector.exe e puoi aprire qualsiasi DLL .net (inclusa la libreria standard). Fornisce una struttura ad albero simile al browser degli oggetti di Visual Studio, tuttavia, puoi fare clic con il pulsante destro del mouse su qualsiasi classe o metodo e fare clic su "disassembla", quindi ti restituirà l'origine in C # o VB, a seconda di quale sia stato selezionato nel opzioni.
statenjason

20

La parola chiave using chiuderà la connessione correttamente, quindi la chiamata aggiuntiva a Close non è richiesta.

Dall'articolo MSDN sul pool di connessioni di SQL Server :

"Ti consigliamo vivamente di chiudere sempre la connessione quando hai finito di utilizzarla in modo che la connessione venga restituita al pool. Puoi farlo utilizzando i metodi Close o Dispose dell'oggetto Connection o aprendo tutte le connessioni all'interno di un utilizzando l'istruzione in C # "

L'attuale implementazione di SqlConnection.Dispose utilizzando .NET Reflector è la seguente:

// 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 per il collegamento MSDN - Mi piace il riflettore \ ILspy come il prossimo ragazzo, ma i documenti sono dove vorrei andare per trovare le mie risposte.
mlhDev

5

Usando Reflector , puoi vedere che il Disposemetodo di SqlConnectionchiama effettivamente Close();

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


3

No, il blocco Utilizzo Dispose()ti chiama comunque, quindi non è necessario chiamare Close().


Mi spiace, avrei dovuto dire che per la maggior parte degli oggetti che implementano IDisposable e hanno un metodo Close (), chiamare Close () finisce comunque per chiamare Dispose () dietro le quinte per te.
Jason Evans

6
Non è il contrario: Dispose()chiamate Close(), non viceversa?
Town

1
Di solito sono entrambe le cose. Per qualche motivo hanno deciso di implementare che Close chiamerebbe anche Dispose. Per un SqlConnection questo non è un grosso problema, ma StreamWriters genererà un'eccezione se li chiudi e poi li elimini. La mia ipotesi è che non cambieranno quel comportamento semplicemente perché è ciò che le persone ora si aspettano.

2

No, non è necessario chiudere una connessione prima di chiamare Dispose.

Alcuni oggetti (come SQLConnections) possono essere riutilizzati dopo aver chiamato Close, ma non dopo aver chiamato Dispose. Per altri oggetti, chiamare Close equivale a chiamare Dispose. (ManualResetEvent e Streams penso si comportino in questo modo)


1

No, la classe SqlConnection eredita da IDisposable e quando viene rilevata la fine dell'utilizzo (per l'oggetto connessione), chiama automaticamente Dispose sulla classe SqlConnection.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.