IQueryable ve IEnumerable arasındaki fark nedir


Yanıtlar:


186

IEnumerable<T>, yalnızca ileri imlecini temsil eder T. .NET 3.5, LINQ standard query operatorsbenzerleri içeren Whereve Firsttahminler veya anonim işlevler gerektiren herhangi bir işleç içeren uzantı yöntemleri ekledi Func<T>.

IQueryable<T>aynı LINQ standart sorgu operatörlerini uygular, ancak Expression<Func<T>>tahminleri ve anonim fonksiyonları kabul eder . Expression<T>derlenmiş bir ifade ağacı, yöntemin sağlayıcı tarafından ayrıştırılabilen ve buna göre kullanılabilen ("eğer yarı yarıya derlenmiş") yöntemin parçalanmış bir sürümüdür.

Örneğin:

IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

İlk blokta, diğer herhangi bir yöntem gibi yürütülebilir x => x.Age > 18anonim bir yöntem ( Func<Person, bool>) bulunur. yöntemin döndürüldüğü değerleri vererek yöntemi Enumerable.Whereher kişi için bir kez yürütür .yieldtrue

İkinci blokta, "'Yaş' özelliği> 18" olarak düşünülebilecek x => x.Age > 18bir ifade ağacı ( Expression<Func<Person, bool>>) bulunur.

Bu, ifade ağacını ayrıştırabildiği ve eşdeğer SQL'e dönüştürebildiği için LINQ-to-SQL gibi şeylerin var olmasını sağlar. Ve sağlayıcının IQueryablenumaralandırılıncaya kadar yürütmesi gerekmediğinden (sonuçta uygular IEnumerable<T>), tüm sorgunun temel verilere karşı nasıl yürütüleceği konusunda daha akıllı seçimler yapmak için birden fazla sorgu operatörünü birleştirebilir (yukarıdaki örnekte Whereve FirstOrDefault) kaynak ( SELECT TOP 1SQL'de kullanmak gibi ).

Görmek:


1
oldukça kısa cevap
ashveli

83

Gerçek hayatta, eğer LINQ-to-SQL gibi bir ORM kullanıyorsanız

  • Bir oluşturursanız IQueryable, sorgu sql'ye dönüştürülebilir ve veritabanı sunucusunda çalıştırılabilir.
  • Bir oluşturursanız IEnumerable, sorguyu çalıştırmadan önce tüm satırlar nesne olarak belleğe alınır.

Her iki durumda da bir ToList()veya ToArray()daha sonra arama yapılmazsa sorgu her kullanıldığında yürütülür, yani diyelim ki sizden bir IQueryableve 4 liste kutusu doldurursanız, sorgu 4 kez veritabanında çalıştırılır.

Ayrıca sorgunuzu genişletirseniz:

q.Select(x.name = "a").ToList()

Sonra IQueryableoluşturulan bir SQL içerecektir where name = "a", ancak IEnumerabledaha birçok rol ile veritabanından geri çekilecek, daha sonra x.name = "a"kontrol .NET tarafından yapılacaktır.


"sorgu sql dönüştürülebilir": 'olabilir' alamadım. Ayrıca, bir IEnumerable var ve bir 'karmaşık zincir' oluşturmak sonra (tabii ki) IQueryable aksine, 'optimize edilmiş' bir SQL sorguya çevrilmez. 'Tüm satırlar belleğe çekilecek' dediğinde bunun ne anlama geldiğini doğrulamak istiyorum. Diyelim ki iki yerde yan tümcelerim var, o zaman varlıkların tüm grupları önce belleğe alınacak ve sonra normal 'bellek içi' filtreleme gerçekleşecek mi?
Vaibhav

36

"Birincil fark, IQueryable için tanımlanan genişletme yöntemlerinin Func nesneleri yerine Expression nesneleri almasıdır, yani aldığı temsilci çağırmak için bir yöntem yerine bir ifade ağacıdır. IEnumerable bellek içi koleksiyonlarla çalışmak için mükemmeldir, ancak IQueryable izin verir veritabanı veya web hizmeti gibi uzak bir veri kaynağı için "

Kaynak: burada


19

IEnumerable IEnumerable en iyi bellek içi toplama ile çalışmak için uygundur. IEnumerable öğeler arasında hareket etmez, yalnızca ileriye dönük koleksiyondur.

IQueryable IQueryable uzak veri kaynağı için bir veritabanı veya web servisi gibi en uygun. IQueryable, çeşitli ilginç ertelenmiş yürütme senaryoları (sayfalama ve kompozisyon tabanlı sorgular gibi) sağlayan çok güçlü bir özelliktir.

Bu nedenle, sadece bellek içi koleksiyonu yinelemeniz gerektiğinde, IEnumerable'ı kullanın, Veri Kümesi ve diğer veri kaynakları gibi koleksiyonla herhangi bir manipülasyon yapmanız gerekiyorsa, IQueryable kullanın


11

Temel fark, IEnumerable'ın tüm öğelerini her zaman numaralandırmasıdır, IQueryable ise bir sorguya dayalı öğeleri numaralandırır, hatta başka şeyler yapar. Sorgu, bir IQueryProvider'ın sonuçları oluşturmak için herhangi bir şeyi keşfetmesi / yorumlaması / derlemesi gereken bir İfadedir (.Net kodunun veri gösterimi).

Bir sorgu ifadesine sahip olmak iki avantaj sağlar.

İlk avantaj optimizasyon. 'Where' gibi değiştiriciler sorgu ifadesine dahil edildiğinden, IQueryProvider aksi takdirde imkansız optimizasyonlar uygulayabilir. Sağlayıcı, 'Where' yantümcesi nedeniyle tüm öğeleri döndürmek ve çoğunu atmak yerine belirli bir anahtarla öğeleri bulmak için bir karma tablo kullanabilir.

İkinci avantaj esnekliktir. İfadeler keşfedilebilir veri yapıları olduğundan, sorguyu serileştirmek ve uzaktaki bir makineye (ör. Linq--sql) göndermek gibi şeyler yapabilirsiniz.



1

Öncelikle IEnumerable bir System.Collections Ad Alanı'nda bulunurken IQueryable bir System.Linq Ad Alanı'nda bulunur. Liste, Dizi koleksiyonu vb. Gibi bellek içi koleksiyonlardan veri sorgularken IEnumerable kullanıyorsanız ve IQueryable kullanmak için bellek dışı (uzak veritabanı, hizmet gibi) koleksiyonlarından veri sorgularken. Veritabanından veri sorgularken, IEnumerable sunucu tarafında seçme sorgusu yürütmek, istemci tarafında bellekte veri yüklemek ve sonra veri filtre. Böylece daha fazla iş yapar ve yavaşlar. Veritabanından veri sorgularken, IQueryable tüm filtrelerle sunucu tarafında seçme sorgusu yürütür. Böylece daha az iş yapar ve hızlı olur.

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.