Perché chiamare SqlClient.SqlDataReader metodo Close() comunque?

È SqlClient.SqlDataReader un .NET managed object o no?
Perché dobbiamo chiamare il metodo Close() in modo esplicito aprire e chiudere la connessione?
Non dovrebbe correre fuori dell’ambito di un oggetto automaticamente chiudere questo?
Non dovrebbe garbage collector pulire comunque?

Per favore aiutami a capire qual è la migliore pratica qui.

Ho visto una domanda correlata qui e illustra ulteriormente il problema che ho con una applicazione web. Il problema è che siamo stati in esecuzione di connessioni. La mappa errore è qui:

Exception: System.InvalidOperationException
Message: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Source: System.Data 

at  System.Data.SqlClient.SqlConnectionPoolManager.GetPooledConnection(SqlConnectionString options, Boolean& isInTransaction)
at  System.Data.SqlClient.SqlConnection.Open()

Per risolvere questo problema, ho dovuto chiudere in modo esplicito tutte le SQLDataReader oggetti.

Sto usando .NET Framework 3.5

InformationsquelleAutor Julius A | 2008-10-30

 

8 Replies
  1. 35

    Sicuro, saranno raccolti quando si va al di fuori del campo di applicazione (se loro sono altri riferimenti). Al momento della raccolta, sarà chiusa attraverso il suo metodo Dispose (). Tuttavia, non si sa mai quando il GC sta per rilasciare le cose; se non chiudi i tuoi lettori, è molto rapidamente a corto di connessioni al database.

    Ulteriore Lettura

    ~ William Riley-Terra

    • upvote per l’ulteriore lettura collegamenti.
    • Dovrebbe menzionare la CommandBehavior.CloseConnection parametro di opzione, che elimina la latenza tra smaltire e l’effettiva raccolta dei rifiuti, quando la connessione sarà rilasciato per ADO piscina
    • il GC non chiamare Dispose quindi non ci contare. Si chiama Finalizzare.
  2. 17

    @Tenente Gelo

    Come una regola nel nostro negozio, abbiamo esplicitamente
    avvolgere tutte le chiamate al database in un
    Blocco Try…Finally, con finalmente
    la sezione di cattura e i dati di chiusura
    le connessioni. Vale la pena spendere un pochino
    di sforzo per salvare se stessi un grande
    risoluzione dei problemi di mal di testa.

    Ho una regola simile, ma ho bisogno che gli oggetti di attuazione IDisposable utilizzare il ‘utilizzando’ il blocco.

    using (SqlConnection conn = new SqlConnection(conStr))
    {
         using (SqlCommand command = new SqlCommand())
         {
            //ETC
         } 
    }

    Blocco chiamate Disporre immediatamente al momento di lasciare il campo di applicazione, anche con un’eccezione.

    • Questa la regola suona bene ed elegante, dovrei prendere in prestito per il mio negozio
    • Interessante. Io gioco con questo e vedi se ti funziona. Mi piace questo molto meglio, comunque.
    • Fa un blocco per il DataReader alcun beneficio qui, o è il blocco per il collegamento è sufficiente? ad esempio, utilizzando (IDataReader dr = comando.ExecuteReader())
    • e se il lettore può non essere istanziato all’interno di blocchi ad esempio, viene passato come parametro out o di essere riutilizzati o …?
    • Troppi inutilizzate = troppa confusione, IMHO. Ma, naturalmente, chiunque può avere le proprie preferenze. E, come è stato notato, ci sono volte che un utilizzo di istruzione non può essere utilizzato.
  3. 10

    Una buona pratica (purché non si ri-utilizzo delle connessioni) è quello di aggiungere il Comando Comportamento SqlDataReader per chiudere la connessione quando viene smaltito:

    SqlDataReader rdr = cmd.ExecuteReader( CommandBehavior.CloseConnection );

    Aggiungere questo farà sì che la connessione al database viene chiuso quando l’oggetto SqlDataReader è chiuso (o garbage collection).

    Come ho detto prima, però, non si vuole fare questo se hai intenzione di riutilizzare la connessione al database per un’altra operazione all’interno del metodo stesso.

  4. 4

    Penso che tutti gli altri ha detto questo, ma ho voluto essere chiaro:

    Al di fuori dell’ambito non significa immediata raccolta dei rifiuti.

    L’app ‘bel gioco’, su un numero di livelli.
    Chiudere le connessioni ti aiuta a farlo.
    Esaminiamo alcuni di questi livelli.

    1: non fare affidamento sulla raccolta dei rifiuti.
    Idealmente garbage collection non c’è bisogno di esistere. Ma lo fa.
    Ma sicuramente la maggior parte non si dovrebbe fare affidamento su di esso.

    2: non sono in possesso delle connessioni al database.
    Mentre le connessioni sono di solito in pool, come hai trovato c’è un limite.
    Tenendo questo in più del necessario rende l’applicazione bad apple.

    3: non generi traffico di rete.
    Ogni connessione al database è essenzialmente una connessione TCP.
    Mantenendo aperte probabilmente genera traffico di rete lungo le linee di
    Siete ancora lì? sì.
    Piccolo traffico di sì, ma in un affollato di rete, questa è una cattiva pratica.
    E SQL Server utilizza le risorse per mantenere la connessione vivo.
    Risorse di altre persone che cercano di avere a che sql server è in grado di fare un uso migliore delle.

    Quando si parla di accesso al database si devono anche pensare a risorse di rete.
    Alcuni modi per ottenere i dati sono cattivi perché può portare oggetti superflui per il lungo viaggio. Le versioni precedenti di ADO, sono stati di tipo noto per questo tipo di cose. Riportare lo schema info quando si desidera solo i dati. Certo, con solo un paio di collegamenti che questo non è un problema. Ma quando mai un qualsiasi database sono solo un paio di collegamenti. Quindi penso a queste cose e cercare di non abusare di risorse.

    Quando il vostro web app ha solo 100 utenti, è possibile che non si cura.
    Ma che cosa circa 100.000? Sempre considerare cosa succede quando si scala.

  5. 3

    Se non esplicitamente vicino, poi si siede lì in attesa per il garbage collector per “raccogliere”… Solo dopo tale verifica viene rilasciato al ADO.Net pool di connessioni per essere riutilizzato da un’altra Connessione.Richiesta di apertura, in modo che durante tutto il tempo per gli interventi, le eventuali altre richieste di connessione, sarà necessario creare un nuovo marchio, anche se c’è una perfettamente buona seduto lì inutilizzati che potrebbero essere utilizzati…

    A seconda del tempo prima che il GC viene eseguito, e quante richieste di Database vengono eseguite, è possibile eseguire disponibili le connessioni al database.

    Ma c’è un parametro opzionale di Comando.ExecuteReader() il metodo, chiamato CommandBehavior. Questa è un’enumerazione, con i valori:
    CommandBehavior.Di Default, CommandBehavior.SingleResult, CommandBehavior.SchemaOnly, CommandBehavior.KeyInfo, CommandBehavior.SingleRow, CommandBehavior.SequentialAccess, e CommandBehavior.CloseConnection

    Questa enumerazione è un attributo FlagsAttribute che consente un’operazione di combinazione dei valori dei membri. È l’ultimo valore, (CommandBehavior.CloseConnection) che qui interessa. Si dice che l’oggetto Comando per chiudere la connessione quando il lettore di dati è chiuso.
    http://msdn.microsoft.com/en-us/library/system.data.commandbehavior.aspx

    Purtroppo l’impostazione di default è di NON chiudere la connessione quando il lettore di dati è chiuso, ma si può (e dovrebbe) passare questo parametro, come CommandBehavior.CloseConnection quando si desidera che il metodo per rilasciare la connessione al pool immediatamente quando hai finito con esso…

  6. 2

    La ‘riuscita’ delle risorse di cui all’con il termine “codice gestito’ è la memoria. Che è. Qualsiasi altra risorsa scarsa, deve essere avvolto con il modello usa e getta, tra cui le connessioni al database.

    La ragione per cui questo è un problema per voi è che il garbage collector non viene eseguito per ogni oggetto al momento fuori del campo di applicazione. È molto più efficace per raccogliere più elementi meno frequentemente. Quindi, se si attende per il collezionista, per smaltire gli oggetti (e sì, se si implementa idisposable che alla fine si) è, forse, essere in possesso di un numero di connessioni al database aperto molto più a lungo di quanto si creda.

  7. 2

    Anche prendere in considerazione ciò che accade quando un’eccezione viene generata, non si può mai sapere se la connessione verrà chiusa se improvvisamente costretto a lasciare il codice in esecuzione.

    Come una regola nel nostro negozio, abbiamo esplicitamente avvolgere tutte le chiamate al database in un blocco Try…Finally, con infine la sezione di cattura e chiudere le connessioni dati. Vale la pena spendere un po ‘ di sforzo per salvare se stessi una maggiore risoluzione dei problemi di mal di testa.

    • L’uso di’ costruire è più elegante, e garantirà l’oggetto è disposto con lo stesso grado di certezza “finalmente”.
    • che cosa è più “elegante” è, sicuramente, una questione di gusto personale. Dal momento che entrambi i metodi per gestire l’oggetto con lo stesso grado di certainity’. Personalmente, preferisco fare affidamento su di codice che dice che cosa sta facendo. Un’istruzione using non dire è lo smaltimento e qual è lo smaltimento, ma, infine, istruzione, si può essere sicuri di smaltire quello che è scritto lì, e niente di più o di meno. Assunzioni è la radice di molti problemi.
  8. 1

    Non è la Connessione che è il problema, ma il Cursore SQL tenuta dalla SqlDataReader. Se si tenta di aprire un secondo senza chiudere il primo, verrà generata un’eccezione.

Lascia un commento