Quanto è male non disporre di () SqlConnections?


14

Personalmente, esplodo negli alveari se non inserisco oggetti ADO che implementano IDisposable nell'uso delle istruzioni. Ma al mio attuale contratto, ho scoperto che il loro codice "provider di accesso ai dati" del framework aziendale nostrano non 1) implementa IDisposable e 2) chiama Dispose () su qualsiasi cosa utilizzi, in qualsiasi momento, in assoluto. Gli utenti si sono lamentati molto dei problemi di prestazioni nelle applicazioni Winforms che utilizzano pesantemente questo framework per l'accesso ai dati, e sebbene ci siano MOLTI altri problemi nel codice che potrebbero colpire le prestazioni, questo mi urla solo ed è più frutti a bassa pendenza rispetto agli altri.

Quindi, oltre a dire qualcosa come "Dispose is there for a reason, use it", cosa posso dire a queste persone per convincerli che questo è davvero, davvero male?


5
Eh ... la mia ipotesi è che, ad un certo punto, non sarà necessario convincere :)
Dr Hannibal Lecter

Risposte:


6

Direi che la cosa migliore che puoi fare è indicarli ai modelli e alle pratiche di Microsoft in merito Dispose() qui . Consenti loro di vedere tutte le conseguenze del non utilizzo di questo strumento proprio di fronte a loro.


1
Vorrei solo poter trovare una versione che non gridasse "questo è contenuto ritirato" in alto.
AJ Johnson,

Sai, i miei occhi sono appena passati su quello. Ma ora leggendolo attentamente, mi chiedo quali tecnologie le persone potrebbero "continuare a utilizzare" che sono ritirate da quella pagina. Forse CAS?
Jesse C. Slicer,

Scansionandolo più da vicino, la maggior parte di questo mi sembra ancora rilevante. Non so perché sia ​​contrassegnato come ritirato.
AJ Johnson,

10

Se non si chiama il metodo Dispose su una connessione SQL, al termine dell'utilizzo, tale connessione NON viene restituita al pool di connessioni.

Se si verificano problemi di prestazioni, suppongo che nel database siano aperte le connessioni massime. Un DBA potrebbe facilmente confermarlo.

Le migliori pratiche di Microsoft richiedono di inserire il codice di connessione all'interno di un'istruzione Using, assicurando che la connessione venga eliminata e che la connessione venga restituita al pool.


La chiamata Closeè sufficiente per tornare al pool di connessioni. La domanda non Closeindica che non è esplicitamente utilizzata.
user2864740

9

Il pool di connessioni al database ha dimensioni limitate e, se si riempie, le nuove connessioni attenderanno il rilascio delle connessioni precedenti. Se non li disponi non appena hai finito con loro, alla fine verranno rilasciati quando il finalizzatore verrà eseguito, ma in futuro sarà un tempo indeterminato ... Quindi, nella migliore delle ipotesi, lo farai vedere lunghi ritardi all'apertura di nuove connessioni.

Nel peggiore dei casi, potrebbero aver disabilitato il pool di connessioni. Forse hanno scoperto che dopo un po 'la loro app stava restituendo errori di "timeout in attesa di connessione" e disabilitando il pool di connessioni "risolto" quel problema. Tuttavia, questo è molto peggio perché significa che stai creando una connessione completamente nuova ogni volta, il che è sorprendentemente ad alta intensità di risorse. Se hai centinaia di connessioni aperte al database, non c'è da meravigliarsi se riscontri problemi di prestazioni.

Il modo corretto per risolvere tutti questi problemi è eliminare la connessione non appena hai finito. L'idea migliore è di mantenere la connessione aperta per tutto il tempo necessario e non più.


1
È anche un po 'peggio di così. Se il pool viene sottoposto a backup a sufficienza, molti tentativi di connessione alla fine falliranno, inclusi i tentativi di connessione dagli strumenti di gestione, e sarà possibile bloccare efficacemente il nostro database.
Joel Coehoorn,

3

In qualsiasi applicazione seria direi che è piuttosto male. Non solo lascerà questi oggetti fluttuare attorno alle prestazioni di uccisione, ma è anche semplicemente poco professionale. La buona notizia è che Microsoft implementa Finalize nella gerarchia degli oggetti.

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

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

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

Prendi System.Data.SqlClient.SqlConnectionad esempio:

System.ComponentModel.Component <- Implementa il modello Dispose finalizza.
    |
System.Data.Common.DbConnection
    |
System.Data.SqlClient.SqlConnection

Gli oggetti verranno infine eliminati, ma la natura non deterministica provoca il caos delle prestazioni.


0

Bene, per uno, non stai terminando la connessione. Quindi deve o a) essere lasciato cadere automaticamente oppure b) passare in rassegna e aggiornato anche se il client non ha alcuna utilità.

Suppongo b) a causa del colpo di performance che stai descrivendo. Tuttavia, questo non è probabilmente l'unico motivo.

DEVI chiudere le tue connessioni, preferibilmente sul lato client, ma devi anche implementare un fail-safe sul lato server. Altrimenti hai appena accumulato una merda in più che il tuo server di database deve elaborare fino a quando non viene rilasciato su god-know-when.

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.