Devo fechar () um SQLConnection antes de ser descartado?

113

Por minha outra pergunta aqui sobre objetos descartáveis , devemos chamar Close () antes do final de um bloco de uso?

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
fonte

Respostas:

107

Como você tem um bloco using, o método Dispose do comando SQLC será chamado e fechará a conexão:

// 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
fonte
1
Faz this._poolGroup = null; significa que a conexão não está voltando para o pool de conexão? então eu terei conexões n-1?
Royi Namir
25

Desmontagem de SqlConnection usando .NET Reflector :

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

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

Ele chama Close () dentro de Dispose ()

statenjason
fonte
1
@statenjason: você poderia dizer como você aproveita as vantagens do uso de desmontadores de linha .net refletor?
odiseh
3
@odiseh basta baixar o .NET Reflector, executar o reflector.exe e você pode abrir qualquer DLL .net (incluindo a biblioteca padrão). Ele fornece uma estrutura de árvore semelhante ao navegador de objetos do Visual Studio, no entanto, você pode clicar com o botão direito em qualquer classe ou método e clicar em "desmontar"; em seguida, retornará a fonte para você em C # ou VB, o que quer que você tenha selecionado no opções.
statenjason
20

A palavra-chave using fechará a conexão corretamente, de forma que a chamada extra para Fechar não é necessária.

Do artigo MSDN sobre pool de conexão do SQL Server :

"É altamente recomendável que você sempre feche a conexão quando terminar de usá-la, para que ela retorne ao pool. Você pode fazer isso usando os métodos Close ou Dispose do objeto Connection ou abrindo todas as conexões dentro de um usando declaração em C # "

A implementação real de SqlConnection.Dispose usando .NET Reflector é a seguinte:

// 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
fonte
1
+1 para link MSDN - Eu gosto de reflector \ ILspy como o próximo cara, mas os documentos são onde eu gostaria de encontrar minhas respostas.
mlhDev
5

Usando o Reflector , você pode ver que o Disposemétodo de SqlConnectionrealmente chama 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
fonte
3

Não, ter o bloco Using chama Dispose()para você de qualquer maneira, então não há necessidade de chamar Close().

Jason Evans
fonte
Desculpe, eu deveria ter dito que para a maioria dos objetos que implementam IDisposable e têm um método Close (), chamar Close () acaba chamando Dispose () nos bastidores para você de qualquer maneira.
Jason Evans
6
Não é o contrário - Dispose()chamadas Close(), não vice-versa?
Cidade de
1
Geralmente são os dois. Por alguma razão, eles decidiram implementar que Close chamaria Dispose também. Para um SqlConnection, isso não é grande coisa, mas StreamWriters lançará uma exceção se você fechar e, em seguida, descartá-los. Meu palpite é que eles não vão mudar esse comportamento simplesmente porque é o que as pessoas agora esperam.
2

Não, não é necessário fechar uma conexão antes de chamar Dispose.

Alguns objetos, (como SQLConnections) podem ser reutilizados após a chamada de Close, mas não após a chamada de Dispose. Para outros objetos, chamar Close é o mesmo que chamar Dispose. (ManualResetEvent e Streams, acho que se comportam assim)

pipTheGeek
fonte
1

Não, a classe SqlConnection herda de IDisposable e, quando o fim do uso (para o objeto de conexão) é encontrado, ele chama automaticamente Dispose na classe SqlConnection.

blparker
fonte