Quão ruim é não Dispose () SqlConnections?


14

Pessoalmente, eu participo em colmeias se não colocar objetos ADO que implementam IDisposable no uso de instruções. Mas, no meu contrato atual, descobri que o código de "provedor de acesso a dados" da estrutura corporativa doméstica não 1) implementa IDisposable e 2) chama Dispose () em qualquer coisa que ele use, a qualquer momento. Os usuários têm reclamado bastante sobre problemas de desempenho nos aplicativos WinForms que usam fortemente essa estrutura para acesso a dados e, embora existam muitos outros problemas no código que poderiam estar atingindo o desempenho, este apenas grita comigo e é mais frutas mais baixas do que as outras.

Portanto, além de dizer algo como "Dispose existe por uma razão, use-o", o que posso dizer a essas pessoas para convencê-las de que isso é muito, muito ruim?


5
Heh..my palpite é que, em algum momento, convincente não será necessário :)
dr Hannibal Lecter

Respostas:


6

Eu diria que a melhor coisa que você pode fazer é apontar para os Padrões e práticas da Microsoft Dispose() aqui . Deixe-os ver todas as consequências de não utilizar esta ferramenta que está bem na frente deles.


1
Gostaria de poder encontrar uma versão que não gritasse "este é um conteúdo desativado" na parte superior.
AJ Johnson

Você sabe, meus olhos simplesmente brilharam sobre isso. Mas agora, lendo-o com atenção, pergunto-me quais tecnologias as pessoas "ainda estão usando" que são retiradas dessa página. Talvez CAS?
Jesse C. Slicer

Analisando-o mais de perto, a maior parte disso ainda me parece relevante. Também não sei por que está marcado como aposentado.
AJ Johnson

10

Se você não chamar o método Dispose em uma conexão SQL, quando terminar de usá-lo, essa conexão NÃO será retornada ao pool de conexões.

Se você está tendo problemas de desempenho, acho que o número máximo de conexões é aberto no seu banco de dados. Um DBA pode confirmar isso facilmente.

As práticas recomendadas da Microsoft solicitam que você insira seu código de conexão dentro de uma instrução Using, garantindo que a conexão seja descartada e que a conexão seja retornada ao pool.


A chamada Closeé suficiente para retornar ao pool de conexões. A questão não afirma que Closenão é usado explicitamente .
user2864740

9

O conjunto de conexões do banco de dados é limitado em tamanho e, se for preenchido, novas conexões aguardarão o lançamento de conexões antigas. Se você não descartá-los assim que você terminar com eles, eles vão finalmente ser liberado quando o finaliser corridas, mas isso é uma quantidade indeterminada de tempo no futuro ... Então, na melhor das hipóteses, você vai veja atrasos ao abrir novas conexões.

Na pior das hipóteses, eles podem ter desativado o pool de conexão. Talvez eles tenham descoberto que depois de um tempo seu aplicativo estava retornando erros de "tempo limite aguardando conexão" e desativando o pool de conexão "resolveu" esse problema. No entanto, isso é muito pior, porque significa que você está criando uma conexão totalmente nova todas as vezes - o que é surpreendentemente intensivo em recursos. Se você tiver centenas de conexões com o banco de dados abertas, não seria de admirar que você esteja tendo problemas de desempenho.

A maneira correta de resolver todos esses problemas é descartar sua conexão assim que terminar. A melhor idéia é manter a conexão aberta pelo tempo exato necessário e não mais.


1
É um pouco pior que isso, até. Se o backup do pool for feito o suficiente, muitas tentativas de conexão acabarão por falhar, incluindo tentativas de conexão das ferramentas de gerenciamento, e você poderá se bloquear efetivamente do banco de dados.
Joel Coehoorn

3

Em qualquer aplicação séria, eu diria que é muito ruim. Não apenas deixar esses objetos flutuando em torno do desempenho de morte, como também é simplesmente não profissional. A boa notícia é que a Microsoft implementa Finalize na hierarquia de objetos.

~Object()
{
    this.Dispose(false);    
}

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // ...
}

Tomemos System.Data.SqlClient.SqlConnectionpor exemplo:

System.ComponentModel.Component <- Implementa o padrão de descarte Finalize.
    |
System.Data.Common.DbConnection
    |
System.Data.SqlClient.SqlConnection

Os objetos serão eventualmente descartados, mas a natureza não determinística causa estragos no desempenho.


0

Bem, por um lado, você não está encerrando a conexão. Portanto, ele deve: a) Ser descartado automaticamente ou b) ser atualizado e atualizado, mesmo que o cliente não tenha utilidade para isso.

Eu diria que b) devido ao desempenho atingido que você está descrevendo. No entanto, esse provavelmente não é o único motivo.

Você DEVE fechar suas conexões, de preferência no lado do cliente, mas também deve implementar uma proteção contra falhas no lado do servidor. Caso contrário, você terá um monte de lixo extra no seu servidor de banco de dados, até que ele seja liberado quando Deus sabe.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.