SqlDataAdapter ve SqlDataReader


131

Bir DB'den veri almak için SqlDataAdapter ve SqlDataReader kullanmak arasındaki farklar nelerdir?

Özellikle Artıları ve Eksileri ile hız ve hafıza performanslarına bakıyorum.

Teşekkürler

Yanıtlar:


194

SqlDataReader:

  • Siz bitirene kadar bağlantıyı açık tutar (kapatmayı unutmayın!).
  • Tipik olarak yalnızca bir kez yinelenebilir
  • Veritabanına geri güncelleme için o kadar kullanışlı değil

Öte yandan, o:

  • Tüm sonuç kümesi yerine tek seferde bellekte yalnızca bir kayıt vardır (bu BÜYÜK olabilir )
  • Bu tek bir yineleme için alabileceğiniz en hızlı
  • Sonuçları daha erken işlemeye başlamanızı sağlar (ilk kayıt mevcut olduğunda). Bazı sorgu türleri için bu çok önemli olabilir.

SqlDataAdapter / DataSet

  • Veri yüklemesi biter bitmez bağlantıyı kapatmanızı sağlar ve hatta sizin için otomatik olarak kapatabilir
  • Tüm sonuçlar hafızada mevcuttur
  • İhtiyaç duyduğunuz kadar üzerinde yineleyebilir, hatta dizine göre belirli bir kayda bakabilirsiniz.
  • Veritabanına geri güncelleme için bazı yerleşik fakülteler var

Pahasına:

  • Çok daha yüksek hafıza kullanımı
  • Herhangi birini kullanmadan önce tüm verilerin yüklenmesini beklersiniz

Yani gerçekten ne yaptığınıza bağlı, ancak yalnızca bir veri kümesi tarafından desteklenen bir şeye ihtiyacım olana kadar Veri Okuyucuyu tercih etme eğilimindeyim. SqlDataReader, salt okunur bir ızgaraya bağlanmanın ortak veri erişimi durumu için mükemmeldir.

Daha fazla bilgi için resmi Microsoft belgelerine bakın .


5
DataSet bir bellek içi veri deposudur, oysa veri okuyucu yalnızca verileri almak için bir ortamdır. Daha açık bir not olarak, Linq sorgularını DataSet üzerinde çalıştırabilirsiniz, ancak bir veri okuyucusunda çalıştıramazsınız.
Partha Choudhury

Aslında, biraz fazladan kodla bir veri okuyucusunda kesinlikle linq sorgularını (veya en az bir sorgu) çalıştırabilirsiniz. DataReader dökümünü döngünüzde bir IDataRecord olarak döndürmek için bir yineleyici bloğu kullanın while (reader.Read()).
Joel Coehoorn

7
Bu cevap yanıltıcıdır. SqlConnection ve SqlDataReader nesnelerinizi "using" ifadeleriyle sararsanız (IDisposable oldukları için yine de yapmanız gerektiği gibi), bağlantı otomatik olarak kapatılır. Ve bir SqlDataReader ile bir DataSet kullanabilirsiniz: sadece DataSet.Load (SqlDataReader) çağırın.
RickNZ

4
@RickNZ İşleri sizin için kapatmak için ifadeleri kullanmaya hemen güvenmeyin. Close () yöntemini değil, nesnenin Dispose () yöntemini çağırıyorlar ve Dispose'un nesneyi benim için gerçekten kapatmadığı en az bir durumla karşılaştım. Using bloğunun içine close yöntemine açık bir çağrı eklemek her zaman en iyisidir.
Cdaragorn

5
@Cdaragorn MSDN belgeleri genellikle Close () ile Dispose () arasında oldukça nettir. Örneğin, SqlConnection durumunda, dokümanlar Close () ve Dispose () işlevlerinin işlevsel olarak eşdeğer olduğunu söyler. Close () 'u çağırmaya herhangi bir itirazım yok, ancak Dispose () çağrıları tüm IDisposable'lar için de orada olmalı - ve bunu yapmanın en temiz yolu using ifadesi kullanmaktır. Dispose () 'un Close ()' u çağırmadığını bildiğiniz durumlarda, kullanım bloğu içinde değil, eğer yapabiliyorsanız, son blok içinde Close () çağırmalısınız (böylece bir istisna varsa yine de çağrılır).
RickNZ

17

Bunun cevabı oldukça geniş olabilir.

Esasen, benim için genellikle kararlarımı etkileyen en büyük fark, bir SQLDataReader ile veritabanından veri "akışlı" olmanızdır. Bir SQLDataAdapter ile, verileri veritabanından kendisi daha fazla sorgulanabilen bir nesneye çıkarır ve CRUD işlemlerini gerçekleştirirsiniz.

Açıkçası bir veri akışı ile SQLDataReader ÇOK daha hızlıdır, ancak bir seferde yalnızca bir kaydı işleyebilirsiniz. Bir SQLDataAdapter ile, kodunuzla çalışmak / geçmek için veritabanından sorgunuzla eşleşen satırların eksiksiz bir koleksiyonuna sahip olursunuz.

UYARI: Eğer bir SQLDataReader kullanıyorsanız, DAİMA, DAİMA bağlantıyı kapatmak için doğru kod yazdığınızdan emin olun, çünkü bağlantıyı SQLDataReader ile açık tuttuğunuzdan. Bunun yapılmaması veya sonuçların işlenmesinde bir hata olması durumunda bağlantının kapatılmasına yönelik uygun hata işleme , uygulamanızı bağlantı sızıntıları ile DÜZELTECEK .

VB'mi bağışlayın, ancak SqlDataReader kullanırken sahip olmanız gereken minimum kod miktarı budur:

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     

eşdeğer C #:

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

Amacınız db üzerinde bir seçme sorgusu kullanarak veri almaksa ve bu verilere yalnızca farklı satırlardan erişmek, sürekli satıra gitmek vb. İse, o zaman SQLDatareader'ı kullanabilir ve dtable.Load (rdr) kullanarak bir veriye yükleyebilirsiniz. Ardından bu veri tablosu içinde yukarı ve aşağı göz atın. DataAdapter yerine bu yöntemi kullanabilirsiniz ...
değişken

14

Bir SqlDataAdapter tipik olarak bir DataSet veya DataTable'ı doldurmak için kullanılır ve bu nedenle bağlantınız kapatıldıktan sonra (bağlantısı kesilen erişim) verilere erişiminiz olur.

SqlDataReader, genellikle bir DataSet / DataTable doldurmaktan daha hızlı olma eğiliminde olan, yalnızca hızlı ileri ve bağlantılı bir imleçtir.

Ayrıca, bir SqlDataReader ile, verilerinizle her seferinde bir kayıt işlemi gerçekleştirirsiniz ve herhangi bir veriyi bellekte tutmazsınız. Açıkça bir DataTable veya DataSet ile, bir bellek ayırma ek yükünüz vardır.

Verilerinizi bellekte tutmanız gerekmiyorsa, bu nedenle yalnızca bir şeyler oluşturmak için SqlDataReader'a gidin. Verilerinizle bağlantısız bir şekilde ilgilenmek istiyorsanız, bir DataSet veya DataTable'ı doldurmak için DataAdapter'ı seçin.


10

Veritabanından bir bellek içi DataSet / DataTable doldurmak istediğinizde bir SqlDataAdapter kullanın. Daha sonra bağlantıyı kapatma / kesme esnekliğine sahip olursunuz, datatable'ı geçirin / bellekte dolaşın. Daha sonra verileri işleyebilir ve InsertCommand / UpdateCommand ile birlikte veri bağdaştırıcısını kullanarak DB'de saklayabilirsiniz.

Verileri iş mantığınız etrafında geçirme esnekliğine ihtiyaç duymadan hızlı, düşük bellek ayak izine sahip veri erişimi istediğinizde bir SqlDataReader kullanın. Bu, tüm verileri tek seferde belleğe yüklemediğinden, büyük veri hacimlerinin hızlı, düşük bellek kullanımı alımı için daha uygundur - SqlDataAdapter yaklaşımıyla, DataSet / DataTable tüm verilerle doldurulur, bu nedenle tutmak için çok fazla bellek gerektiren çok sayıda satır ve sütun var.


0

Doldurma işlevi dahili olarak bir Veri Okuyucusu kullanır. Düşünceniz "Hangisi daha verimli?" İse, o zaman kayıt bazında koleksiyonu dolduran sıkı bir döngüde bir DataReader kullanmak, muhtemelen sistemdeki DataAdapter.Fill'i kullanmakla aynı yük olacaktır.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.