SqlDataAdapter vs SqlDataReader


130

Quali sono le differenze tra l'utilizzo di SqlDataAdapter e SqlDataReader per ottenere dati da un DB?

Sto specificamente esaminando i loro pro e contro, nonché le loro prestazioni di velocità e memoria.

Grazie

Risposte:


193

SqlDataReader:

  • Mantiene la connessione aperta fino al termine (non dimenticare di chiuderla!).
  • In genere può essere ripetuto una sola volta
  • Non è utile per l'aggiornamento al database

D'altra parte, esso:

  • Ha un solo record in memoria alla volta anziché un intero set di risultati (questo può essere ENORME )
  • È il più veloce possibile per quella iterazione
  • Ti consente di iniziare a elaborare i risultati prima (una volta che il primo record è disponibile). Per alcuni tipi di query questo può anche essere un grosso problema.

SqlDataAdapter / DataSet

  • Ti consente di chiudere la connessione non appena ha terminato il caricamento dei dati e potrebbe anche chiuderla automaticamente per te
  • Tutti i risultati sono disponibili in memoria
  • Puoi iterare su di esso tutte le volte che ti serve o anche cercare un record specifico per indice
  • Ha alcune facoltà integrate per l'aggiornamento al database

Al costo di:

  • Utilizzo della memoria molto più elevato
  • Attendi il caricamento di tutti i dati prima di utilizzarli

Quindi dipende davvero da cosa stai facendo, ma tendo a preferire un DataReader fino a quando non ho bisogno di qualcosa che è supportato solo da un set di dati. SqlDataReader è perfetto per il caso comune di accesso ai dati di associazione a una griglia di sola lettura.

Per ulteriori informazioni, consultare la documentazione ufficiale di Microsoft .


5
DataSet è un archivio dati in memoria, mentre datareader è solo un mezzo per recuperare i dati. Su una nota più leggera, è possibile eseguire query Linq su DataSet, ma non su un datareader.
Partha Choudhury,

In realtà, con un po 'di codice extra puoi certamente eseguire query linq (o, almeno una query) su un datareader. Usa semplicemente un blocco iteratore per restituire il cast di DataReader come IDataRecord all'interno del tuo while (reader.Read())loop.
Joel Coehoorn,

7
Questa risposta è fuorviante. Se avvolgi i tuoi oggetti SqlConnection e SqlDataReader con istruzioni "using" (come dovresti comunque, dato che sono IDisposable), la connessione verrà chiusa automaticamente. E puoi usare un DataSet con un SqlDataReader: basta chiamare DataSet.Load (SqlDataReader).
RickNZ,

4
@RickNZ Non essere troppo veloce nel fidarti delle dichiarazioni per chiudere le cose per te. Chiamano il metodo Dispose () dell'oggetto, non il metodo Close (), e mi sono imbattuto in almeno un caso in cui il Dispose non ha effettivamente chiuso l'oggetto per me. È sempre meglio includere una chiamata esplicita al metodo close all'interno del blocco using.
Cdaragorn,

5
@Cdaragorn i documenti MSDN sono generalmente abbastanza chiari su Close () vs. Dispose (). Nel caso di SqlConnection, ad esempio, i documenti affermano che Close () e Dispose () sono funzionalmente equivalenti. Non ho alcuna obiezione a chiamare Close (), ma le chiamate a Dispose () dovrebbero essere presenti anche per tutti gli IDisposable - e il modo più pulito per farlo è con un'istruzione using. Nei casi in cui sai che Dispose () non chiama Close (), allora dovresti chiamare Close () all'interno di un blocco finally, se puoi, non all'interno del blocco using (quindi viene comunque chiamato se c'è un'eccezione).
RickNZ,

17

La risposta a questa può essere piuttosto ampia.

In sostanza, la differenza principale per me che di solito influenza le mie decisioni su cui utilizzare è che con un SQLDataReader, si "streaming" dati dal database. Con un SQLDataAdapter, si estraggono i dati dal database in un oggetto che può essere interrogato ulteriormente, oltre a eseguire operazioni CRUD.

Ovviamente con un flusso di dati SQLDataReader è MOLTO più veloce, ma è possibile elaborare solo un record alla volta. Con un SQLDataAdapter, hai una raccolta completa delle righe corrispondenti alla tua query dal database per lavorare / passare attraverso il tuo codice.

ATTENZIONE: se si utilizza SQLDataReader, SEMPRE, SEMPRE, SEMPRE assicurarsi di scrivere il codice corretto per chiudere la connessione poiché si mantiene aperta la connessione con SQLDataReader. In caso contrario , o la corretta gestione degli errori per chiudere la connessione in caso di un errore nell'elaborazione dei risultati, CRIPPLE l'applicazione con perdite di connessione.

Perdonate il mio VB, ma questa è la quantità minima di codice che dovreste avere quando usate un SqlDataReader:

Using cn As New SqlConnection("..."), _
      cmd As New SqlCommand("...", cn)

    cn.Open()
    Using rdr As SqlDataReader = cmd.ExecuteReader()
        While rdr.Read()
            ''# ...
        End While
    End Using
End Using     

C # equivalente:

using (var cn = new SqlConnection("..."))
using (var cmd = new SqlCommand("..."))
{
    cn.Open();
    using(var rdr = cmd.ExecuteReader())
    {
        while(rdr.Read())
        {
            //...
        }
    }
}

Se il tuo obiettivo è ottenere dati utilizzando una query di selezione su db e accedere a questi dati solo su righe diverse, passare alla riga rpevious, ecc., Puoi utilizzare SQLDatareader e caricarlo in un datatable utilizzando dtable.Load (rdr). Quindi navigare su e giù all'interno di questo datatable. È possibile utilizzare questo metodo anziché DataAdapter ...
variabile

14

Un SqlDataAdapter viene in genere utilizzato per riempire un DataSet o DataTable e quindi si avrà accesso ai dati dopo che la connessione è stata chiusa (accesso disconnesso).

SqlDataReader è un cursore di sola andata veloce e connesso che tende a essere generalmente più veloce della compilazione di un DataSet / DataTable.

Inoltre, con un SqlDataReader, gestisci i tuoi dati un record alla volta e non conservi alcun dato in memoria. Ovviamente con un DataTable o DataSet, hai un overhead di allocazione della memoria.

Se non hai bisogno di conservare i tuoi dati in memoria, quindi solo per il rendering di cose, scegli SqlDataReader. Se si desidera gestire i dati in modo disconnesso, selezionare DataAdapter per compilare un DataSet o DataTable.


10

Utilizzare un SqlDataAdapter quando si desidera popolare un DataSet / DataTable in memoria dal database. Hai quindi la flessibilità di chiudere / eliminare la connessione, passare il datatable / impostare in memoria. È quindi possibile modificare i dati e reinserirli nel DB utilizzando l'adattatore dati, insieme a InsertCommand / UpdateCommand.

Utilizzare un SqlDataReader quando si desidera un accesso rapido e con ingombro ridotto di memoria senza la necessità di flessibilità, ad esempio per il passaggio dei dati nella logica aziendale. Questo è più ottimale per il recupero rapido e con poca memoria di grandi volumi di dati poiché non carica tutti i dati in memoria tutto in una volta - con l'approccio SqlDataAdapter, il DataSet / DataTable verrebbe riempito con tutti i dati, quindi se ci sono molte righe e colonne che richiedono molta memoria per contenere.


0

La funzione Fill utilizza internamente un DataReader. Se la tua considerazione è "Quale è più efficiente?", Allora l'utilizzo di un DataReader in un ciclo stretto che popola una raccolta record per record, probabilmente avrà lo stesso carico sul sistema dell'utilizzo di DataAdapter.Fill.

(System.Data.dll, System.Data.Common.DbDataAdapter, FillInternal.)

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.