2010-08-02 12 views
11

So che ho chiesto una domanda correlata in precedenza. Ho appena avuto un altro pensiero.utilizzando su SQLDataReader

using (SqlConnection conn = new SqlConnection('blah blah')) 
{ 
    using(SqlCommand cmd = new SqlCommand(sqlStatement, conn)) 
    { 
     conn.open(); 

     // *** do I need to put this in using as well? *** 
     SqlDataReader dr = cmd.ExecuteReader() 
     { 
      While(dr.Read()) 
      { 
       //read here 
      } 
     } 
    } 
} 

L'argomento è che: Dato che l'oggetto SqlDataReaderdr non è un nuovo oggetto come il collegamento o di comando gli oggetti, la sua semplicemente un riferimento che punta al metodo di cmd.ExecuteReader(), ho bisogno di mettere il lettore all'interno di un using. (Ora, in base al mio post precedente, è a mia conoscenza che qualsiasi oggetto che utilizza IDisposable deve essere inserito in un using e SQLDataReader ereditato da IDisposable, quindi ho bisogno di metterlo. Sono corretto a mio giudizio?) Sono solo confuso poiché non è un nuovo oggetto, potrebbe causare problemi nello smaltimento di un oggetto che è semplicemente un puntatore di riferimento al comando?

Molte grazie

+0

"cmd.ExecuteReader" è una sorta di metodo di riferimento. "cmd.ExecuteReader()" (parentesi graffe) è una chiamata al metodo. –

risposta

26

Penso che ti sbagli. Lo dr è un riferimento all'oggetto restituito da cmd.ExecuteReader, che diventerà un nuovo oggetto. Nel tuo esempio, nulla disporrà di dr, quindi sì, deve essere in un using o smaltito manualmente.

Il tuo giudizio sugli IDisposable implementatori che devono essere in un using non è corretto. Funzioneranno bene fuori. Un'istruzione using è solo zucchero sintattico per un try ... finally. Le cose che implementano IDisposable devono essere chiamate Dispose, perché stanno segnalando che devono disporre di determinati stati in modo deterministico.

Si noti che se non si chiama Dispose, non è sempre un problema. Alcuni oggetti implementano anche il finalizzatore, che verrà attivato dal garbage collector. Se non implementano il finalizzatore, potrebbero lasciare la memoria non gestita non reclamata. Questo rimarrà non reclamato fino alla chiusura della tua applicazione. Tutta la memoria gestita viene infine recuperata, a meno che non sia idonea per la garbage collection.

riscritta:

using (SqlConnection conn = new SqlConnection('blah blah')) 
using(SqlCommand cmd = new SqlCommand(sqlStatement, conn)) 
{ 
    conn.open(); 
    using (SqlDataReader dr = cmd.ExecuteReader()) 
    { 
     while (dr.Read()) 
     { 
      //read here 
     } 
    } 
} 
+0

sì, capisco che l'uso si traduce semplicemente in un tentativo..finalmente blocco e potrei benissimo chiamare il disporsi. Ma penso che sia meglio prendere l'abitudine di avvolgere il blocco all'interno dell'utilizzo in quanto potrei tendere a dimenticare di inserire il pezzo di codice in try..finnally. Grazie per la risposta. :) – xeshu

+0

Va bene :-) Lo menzionerò anche che SqlDataReader è un nuovo oggetto, o è almeno un riferimento a un oggetto restituito dalla chiamata al metodo, non è un riferimento al metodo. Basta citare perché hai fatto quel punto in maiuscolo e non è corretto. L'unica differenza tra il lettore e la connessione/comando è che hai inizializzato la connessione/comando, ma non hai inizializzato il lettore. Alla fine hai ancora riferimenti a tutti gli oggetti, sia che li inizializzi o no. –

+0

Ah sì. Colpa mia! :) – xeshu

2

Si dovrebbe avvolgere il lettore di dati in una dichiarazione utilizzando come metodo di ExecuteReader è la creazione di una nuova istanza di lettore di dati che dovrebbero anche essere smaltiti.

Problemi correlati