Usuário com melhor resposta
Problema no fechamento de conexão

Pergunta
-
Olá pessoal. Estou tendo um problema no fechamento de conexões com o SQL Server, apenas em Debug.
O que ocorre é que ao tentar fechar a conexão (conexão aberta em Pooling FALSE), tenho a seguinte mensagem, na clinha do método Close():
"InvalidOperationException was unhandled. Handle is not initialized."System.InvalidOperationException was unhandled
Message="Handle is not initialized."
Source="mscorlib"
StackTrace:
at System.WeakReference.set_Target(Object value)
at System.Data.ProviderBase.DbConnectionInternal.CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Close()
at DataBaseLayers.SqlServerLayer.Close() in H:\Controls\DataBaseLayers\SqlServerLayer.cs:line 80
at DataBaseLayers.SqlServerLayer.Finalize() in H:\Controls\DataBaseLayers\SqlServerLayer.cs:line 91Antes do fechamento eu verifico a necessidade do fechamento...
if (conexaoSql.State == ConnectionState.Open)
conexaoSql.Close();Porque disto?!
Respostas
-
Talvez o problema seja esse. Você, como programador, não sabe quando o destrutor da classe é chamado efetivamente. Essa chamada é feita exclusivamente pelo Garbage Collector. O destrutor do objeto connection também é determinado pelo Garbage Collector. Em outras palavras, você não tem determinada a ordem que os objetos são retirados da memória. O que pode estar ocorrendo é que quando o destrutor da sua classe é chamada pelo GC, o objeto conexaoSql pode já ter sido retirado da memória pelo GC. Para resolver isso você pode: 1) fechar a conexão em outro local que não o destrutor, em um método, por exemplo, e chama-lo sempre que não for mais usar a instancia da sua classe; 2)chamar o GC para limpar a memória; 3) Implementar o método Dispose da interface IDisposable, fazendo com que o destrutor seja chamado sempre que terminar de usar os objetos de sua classe.
Espero ter ajudado.
Todas as Respostas
-
-
Olá Daniel. Como a referência não existe mais se eu consigo ver o estado da conexão na linha 1 do código abaixo? Mandei o Debug parar na linha 1 para ver o estado. Quando está Open, vai para a linha 2 (claro!). Algumas vezes fecha e o estado é alterado para Close sem problemas. Mas algumas vezes, a conexão está Open na linha 1 e, antes de executar a linha 2, já está Close!!! Daí, quando executa a linha 2 ocorre esse problema. Será que o negócio é tão eficiente que fecha antes mandar fechar?!
1 if (conexaoSql.State == ConnectionState.Open)
2 conexaoSql.Close();Vlw!
-
-
Frederico, eu sempre fecho a conexão usando um método chamado Close, da minha classe. Este, por sua vez, verifica a necessidade de fechar a conexão ou não. E o Destrutor da classe também está ai embaixo.. mas ele chama o mesmo método, para fazer o tratamento.
public
void Close(){
if (conexaoSql.State == ConnectionState.Open)conexaoSql.Close();
}
~SqlServerLayer()
{
Close();
}
Vlw!
-
Talvez o problema seja esse. Você, como programador, não sabe quando o destrutor da classe é chamado efetivamente. Essa chamada é feita exclusivamente pelo Garbage Collector. O destrutor do objeto connection também é determinado pelo Garbage Collector. Em outras palavras, você não tem determinada a ordem que os objetos são retirados da memória. O que pode estar ocorrendo é que quando o destrutor da sua classe é chamada pelo GC, o objeto conexaoSql pode já ter sido retirado da memória pelo GC. Para resolver isso você pode: 1) fechar a conexão em outro local que não o destrutor, em um método, por exemplo, e chama-lo sempre que não for mais usar a instancia da sua classe; 2)chamar o GC para limpar a memória; 3) Implementar o método Dispose da interface IDisposable, fazendo com que o destrutor seja chamado sempre que terminar de usar os objetos de sua classe.
Espero ter ajudado.
-
Olá Frederico. Eu sempre chamo o Close(). Mas pela boa intenção, eu acabei programando o Destructor para chamá-lo também, mesmo que não seja mais necessário. Talvez tenha pecado pelo excesso de preocupação em fechar a conexão. Mas o que você disse está perfeito, eu não sei quando o destructor é chamado. Ocorre, inclusive, de eu estar com a página já renderizada no browser e o foco ser alterado para dentro do Visual Studio para me informar que ocorreu um erro no fechamento da conexão. Ou seja, o GC trabalhou neste momento, chamando o destructos, que por sua vez chama o (meu) Close. Vou testar ainda, mas estou quase certo de que você foi perfeito no que disse!
-
-