SqlDataAdapter vs SqlDataReader

130

Apa perbedaan antara menggunakan SqlDataAdapter vs SqlDataReader untuk mendapatkan data dari DB?

Saya secara khusus melihat ke Pro dan Kontra mereka serta kecepatan dan kinerja memori mereka.

Terima kasih

stewsha
sumber

Jawaban:

193

SqlDataReader:

  • Biarkan koneksi terbuka sampai Anda selesai (jangan lupa untuk menutupnya!).
  • Biasanya hanya dapat diulangi sekali
  • Tidak berguna untuk memperbarui kembali ke database

Di sisi lain, itu:

  • Hanya memiliki satu catatan dalam memori pada suatu waktu daripada seluruh hasil yang ditetapkan (ini bisa BESAR )
  • Apakah tentang secepat Anda bisa mendapatkan untuk iterasi yang satu itu
  • Memungkinkan Anda mulai memproses hasil lebih cepat (setelah catatan pertama tersedia). Untuk beberapa jenis permintaan ini juga bisa menjadi masalah yang sangat besar.

SqlDataAdapter / DataSet

  • Memungkinkan Anda menutup koneksi begitu selesai memuat data, dan bahkan dapat menutupnya untuk Anda secara otomatis
  • Semua hasil tersedia dalam memori
  • Anda dapat mengulanginya sebanyak yang Anda butuhkan, atau bahkan mencari catatan tertentu berdasarkan indeks
  • Memiliki beberapa fakultas bawaan untuk memperbarui kembali ke database

Dengan biaya:

  • Banyak penggunaan memori yang lebih tinggi
  • Anda menunggu sampai semua data dimuat sebelum menggunakannya

Jadi sebenarnya itu tergantung pada apa yang Anda lakukan, tapi saya cenderung lebih suka DataReader sampai saya membutuhkan sesuatu yang hanya didukung oleh dataset. SqlDataReader sempurna untuk kasus akses data umum yang mengikat ke kotak baca-saja.

Untuk info lebih lanjut, lihat dokumentasi resmi Microsoft .

Joel Coehoorn
sumber
5
DataSet adalah datastore dalam memori, sedangkan datareader hanyalah media untuk mengambil data. Pada catatan yang lebih ringan, Anda bisa menjalankan kueri Linq pada DataSet, tetapi tidak pada datareader.
Partha Choudhury
Sebenarnya, dengan sedikit kode tambahan Anda tentu dapat menjalankan kueri linq (atau, setidaknya satu permintaan) pada datareader. Cukup gunakan blok iterator untuk menghasilkan pengembalian dataReader sebagai IDataRecord di dalam while (reader.Read())loop Anda .
Joel Coehoorn
7
Jawaban ini menyesatkan. Jika Anda membungkus objek SqlConnection dan SqlDataReader Anda dengan pernyataan "menggunakan" (seperti yang seharusnya, karena mereka IDisposable), koneksi akan ditutup secara otomatis. Dan Anda dapat menggunakan DataSet dengan SqlDataReader: cukup panggil DataSet.Load (SqlDataReader).
RickNZ
4
@RickNZ Jangan terlalu cepat mempercayai menggunakan pernyataan untuk menutup sesuatu untuk Anda. Mereka memanggil metode Buang objek (), bukan metode Tutup (), dan saya telah menemukan setidaknya satu kasus di mana Buang tidak benar-benar menutup objek untuk saya. Itu selalu terbaik untuk menyertakan panggilan eksplisit ke metode tutup di dalam blok menggunakan.
Cdaragorn
5
@Cdaragorn dokumen MSDN biasanya cukup jelas tentang Close () vs. Buang (). Dalam kasus SqlConnection, misalnya, dokumen mengatakan bahwa Tutup () dan Buang () secara fungsional setara. Saya tidak keberatan untuk memanggil Close (), tetapi panggilan untuk Buang () harus ada di sana juga untuk semua IDisposables - dan cara terbersih untuk melakukannya adalah dengan menggunakan pernyataan. Dalam kasus di mana Anda tahu Buang () tidak memanggil Tutup (), maka Anda harus memanggil Tutup () dalam blok akhirnya jika Anda bisa, tidak dalam blok menggunakan (jadi masih dipanggil jika ada pengecualian).
RickNZ
17

Jawabannya bisa sangat luas.

Pada dasarnya, perbedaan utama bagi saya yang biasanya mempengaruhi keputusan saya yang akan digunakan adalah bahwa dengan SQLDataReader, Anda "streaming" data dari database. Dengan SQLDataAdapter, Anda mengekstraksi data dari database ke objek yang dapat ditanyakan lebih lanjut, serta melakukan operasi CRUD.

Jelas dengan aliran data SQLDataReader JAUH lebih cepat, tetapi Anda hanya dapat memproses satu catatan pada suatu waktu. Dengan SQLDataAdapter, Anda memiliki koleksi lengkap baris yang cocok untuk permintaan Anda dari database untuk bekerja dengan / melewati kode Anda.

PERINGATAN: Jika Anda menggunakan SQLDataReader, SELALU, SELALU, SELALU pastikan Anda menulis kode yang tepat untuk menutup koneksi karena Anda menjaga koneksi tetap terbuka dengan SQLDataReader. Kegagalan untuk melakukan ini, atau penanganan kesalahan yang tepat untuk menutup koneksi jika terjadi kesalahan dalam memproses hasil akan CRIPPLE aplikasi Anda dengan kebocoran koneksi.

Maafkan VB saya, tetapi ini adalah jumlah minimum kode yang harus Anda miliki saat menggunakan 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     

setara dengan C #:

using (var cn = new SqlConnection("..."))
using (var cmd = new SqlCommand("..."))
{
    cn.Open();
    using(var rdr = cmd.ExecuteReader())
    {
        while(rdr.Read())
        {
            //...
        }
    }
}
Jaywon
sumber
Jika tujuan Anda adalah untuk mendapatkan data menggunakan kueri pemilihan pada db, dan hanya mengakses data ini pada baris yang berbeda, pergi ke baris sebelumnya, dll, maka Anda dapat menggunakan SQLDatareader dan memuatnya ke dalam datatable menggunakan dtable.Load (rdr). Kemudian telusuri ke atas dan ke bawah di dalam data ini. Anda dapat menggunakan metode ini alih-alih DataAdapter ...
variabel
14

SqlDataAdapter biasanya digunakan untuk mengisi DataSet atau DataTable sehingga Anda akan memiliki akses ke data setelah koneksi Anda ditutup (akses terputus).

SqlDataReader adalah kursor hanya maju-maju dan terhubung yang cenderung lebih cepat daripada mengisi DataSet / DataTable.

Selain itu, dengan SqlDataReader, Anda menangani data satu catatan pada satu waktu, dan tidak menyimpan data apa pun di memori. Tentunya dengan DataTable atau DataSet, Anda memiliki overhead alokasi memori.

Jika Anda tidak perlu menyimpan data dalam memori, jadi untuk merender hal-hal saja, buka SqlDataReader. Jika Anda ingin menangani data Anda secara terputus, pilih DataAdapter untuk mengisi DataSet atau DataTable.

Wim Hollebrandse
sumber
10

Gunakan SqlDataAdapter ketika ingin mengisi DataSet / DataTable di dalam memori dari database. Anda kemudian memiliki fleksibilitas untuk menutup / membuang koneksi, meneruskan data / set di memori. Anda kemudian dapat memanipulasi data dan bertahan kembali ke DB menggunakan adaptor data, bersama dengan InsertCommand / UpdateCommand.

Gunakan SqlDataReader ketika menginginkan akses data footprint cepat, memori rendah tanpa perlu fleksibilitas untuk misalnya menyampaikan data di sekitar logika bisnis Anda. Ini lebih optimal untuk pengambilan cepat, memori rendah, volume data besar karena tidak memuat semua data ke dalam memori semua dalam satu waktu - dengan pendekatan SqlDataAdapter, DataSet / DataTable akan diisi dengan semua data jadi jika ada banyak baris & kolom, yang akan membutuhkan banyak memori untuk disimpan.

AdaTheDev
sumber
0

Fungsi Fill menggunakan DataReader secara internal. Jika pertimbangan Anda adalah "Yang mana yang lebih efisien?", Kemudian menggunakan DataReader dalam lingkaran ketat yang mengisi kumpulan catatan-demi-catatan, kemungkinan menjadi beban yang sama pada sistem seperti menggunakan DataAdapter.Fill.

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

billpg
sumber