Arasındaki fark nedir IQueryable<T>ve IEnumerable<T>?
Ayrıca bkz . Bu soru ile çakışan IQueryable ve IEnumerable arasındaki fark nedir ?
Arasındaki fark nedir IQueryable<T>ve IEnumerable<T>?
Ayrıca bkz . Bu soru ile çakışan IQueryable ve IEnumerable arasındaki fark nedir ?
Yanıtlar:
Her şeyden önce, genişleten bir "düz" ile yapabileceğiniz şey, böylece arayüz , aynı zamanda bir ile yapabilirsiniz .IQueryable<T> IEnumerable<T>IEnumerable<T>IQueryable<T>
IEnumerable<T>Sadece bir yer alır GetEnumerator()kullanıcıya bir yöntemi Enumerator<T>, onun çağırabilmesi için MoveNext()bir dizi boyunca yineleme yöntemini T .
Ne IQueryable<T>olduğunu etmiştir IEnumerable<T> gelmez bir işaret söz konusu-birinde iki özellik vardır sorgu sağlayıcısına bir etmek (örneğin, SQL sağlayıcısına bir LINQ) ve başka bir işaret sorgu ifadesinde temsilIQueryable<T> olabilecek bir çalışma zamanı-çaprazlanabiliyorsa soyut sözdizimi ağacı olarak nesneyi verilen sorgu sağlayıcısı tarafından anlaşılır (çoğunlukla, bir istisna oluşturulmadan LINQ to Entities sağlayıcısına SQL ifadesine bir LINQ veremezsiniz).
İfade, nesnenin kendisinin sabit bir ifadesi veya oluşturulmuş bir sorgu işleçleri ve işlenenler kümesinden daha karmaşık bir ağaç olabilir. Sorgu sağlayıcısının IQueryProvider.Execute()veya IQueryProvider.CreateQuery()yöntemlerinin kendisine iletilen bir İfade ile çağrılır ve ardından IQueryablesırasıyla bir sorgu sonucu veya başka bir sonuç döndürülür.
AsQueryable()sadece bir sorgulanabilir numaraya numaralandırılır ve IQueryablearabirimi uygularsa geri döndürür , aksi takdirde ConstantExpressiondöndürülen bir EnumerableQuerynesnede atıfta bulunulan a'ya sarar .
Birincil fark, temsilciler yerine nesne IQueryable<T>almak için LINQ operatörlerinin Expression, yani aldığı bir özel sorgu mantığı, örneğin bir yüklem veya değer seçici gibi, bir yönteme temsilci yerine bir ifade ağacı biçiminde olmasıdır.
IEnumerable<T> bellekte yinelenen dizilerle çalışmak için mükemmeldir, ancak IQueryable<T> veritabanı veya web hizmeti gibi uzak veri kaynağı gibi bellek dışı şeylere izin verir.Bir sorgunun yürütülmesi "işlemde" gerçekleştirilecekse , genellikle gerekli olan tek şey, sorgunun her bir parçasını yürütmek için kullanılan koddur (kod olarak).
Yürütme işlem dışında gerçekleştirilecekse , sorgunun mantığı, LINQ sağlayıcısının, bu bir LDAP sorgusu olsun, bellek dışı yürütme için uygun forma dönüştürülebileceği şekilde verilerde temsil edilmelidir SQL ya da her neyse.
Daha:
IEnumerable<T>veIQueryable<T>IEnumerable<T>dönüyorIQueryable<T> "IEnumerable, IQueryable, IObservableveIQbservable
Bu, youtube'da , bu arayüzlerin nasıl farklı olduğunu, izlemeye değer olduğunu gösteren güzel bir video .
Aşağıda bunun için uzun bir açıklayıcı cevap bulunmaktadır.
Hatırlanması gereken ilk önemli noktadır IQueryablegelen arayüz devralır IEnumerable, her neyse IEnumerableyapabilir, IQueryableayrıca yapabilirsiniz.

Birçok fark var ama en büyük farkı yaratan tek büyük fark hakkında konuşalım. IEnumerablearayüzü, koleksiyonunuz kullanılarak yüklendiğinde kullanışlıdır.LINQ veya Entity framework ve koleksiyona filtre uygulamak istediğinizde .
IEnumerableVarlık çerçevesi ile birlikte kullanılan aşağıdaki basit kodu göz önünde bulundurun . Bir kullanıyor Whereolan kayıtları almak için filtre EmpIdolduğunu 2.
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Bu, filtrenin IEnumerablekodun bulunduğu istemci tarafında yürütüldüğü yerdir . Bir başka deyişle, tüm veriler veritabanından getirilen ve daha sonra onun taramaları istemcide ile kayıt almaktadır EmpIdolduğunu 2.

Ama şimdi değişti aşağıdaki kodu görmek IEnumerableiçin IQueryable. Sunucu tarafında bir SQL Sorgusu oluşturur ve istemci tarafına yalnızca gerekli veriler gönderilir.
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();

Arasındaki fark Yani IQueryableveIEnumerable filtre mantığı gerçekleştirildiği yer hakkındadır. Biri istemci tarafında, diğeri veritabanında yürütülür.
Bu yüzden sadece bellek içi veri toplama ile çalışıyorsanız IEnumerableiyi bir seçimdir, ancak veritabanına bağlı veri toplama sorgulamak istiyorsanız `IQueryable ağ trafiğini azalttığı ve SQL dilinin gücünü kullandığı için daha iyi bir seçimdir.
IEnumerable: IEnumerable, bellek içi toplama (veya yerel sorgular) ile çalışmak için en uygun yöntemdir. IEnumerable öğeler arasında hareket etmiyor, sadece ileriye doğru toplama.
IQueryable: Veritabanı veya web hizmeti (veya uzak sorgular) gibi uzak veri kaynağı için en uygun IQueryable. 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
Gerçek hayatta, eğer LINQ-to-SQL gibi bir ORM kullanıyorsanız
Her iki durumda da bir ToList()veya ToArray()daha sonra sorguyu kullanmazsanız, sorgu her kullanıldığında yürütülür, yani diyelim ki, ondan bir IQueryable<T>liste kutusu doldurursunuz ve sorgu 4 kez veritabanında çalıştırılır.
Ayrıca sorgunuzu genişletirseniz:
q.Where(x.name = "a").ToList()
Daha sonra bir IQueryable ile oluşturulan SQL “nerede name =“ a ”içerecektir, ancak bir IEnumerable ile daha birçok rol veritabanından geri alınacak, daha sonra x.name =“ a ”kontrolü .NET tarafından yapılacaktır.
Aşağıda belirtilen küçük test IQueryable<T>ve ile arasındaki farkın bir yönünü anlamanıza yardımcı olabilir IEnumerable<T>. Başka bir kişinin gönderisine düzeltme eklemeye çalıştığım bu gönderiden bu yanıtı yeniden oluşturdum
Ben DB (DDL komut dosyası) aşağıdaki yapı oluşturdu:
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
İşte kayıt ekleme komut dosyası (DML komut dosyası):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
Şimdi, amacım Employeeveritabanındaki tablodan en iyi 2 kaydı almaktı. Konsol uygulamama Employeeveritabanımdaki tabloya işaret eden bir ADO.NET Varlık Veri Modeli öğesi ekledim ve LINQ sorguları yazmaya başladım.
IQueryable yolu için kod :
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Bu programı çalıştırmaya başladığımda, SQL Server örneğimde bir SQL Query profiler oturumu başlatmıştım ve işte yürütmenin özeti:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]Sadece yan tümcesi veritabanı sunucu tarafı kendisi IQueryableuygulamak için yeterince akıllıdır, Top (2)böylece tel üzerinden 5 kayıt sadece 2 getiriyor. İstemci bilgisayar tarafında daha fazla bellek içi filtreleme gerekmez.
Sayılabilir rota kodu :
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Bu durumda yürütmenin özeti:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]Şimdi şey, tablodaki IEnumerable5 kaydın tümünü getirildi Salaryve daha sonra istemci bilgisayarda en iyi 2 kaydı almak için bir bellek içi filtreleme gerçekleştirildi. Böylece gereksiz yere tel üzerinden daha fazla veri (bu durumda 3 ek kayıt) aktarıldı.
İşte benzer bir yazıya yazdım (bu konuda). (Ve hayır, genellikle kendimi teklif etmiyorum, ama bunlar çok iyi makaleler.)
"Bu makale faydalıdır: LINQ-to-SQL'de IQueryable vs IEnumerable .
Bu makalede, 'MSDN belgelerine göre, IQueryable üzerinde yapılan çağrılar bunun yerine dahili ifade ağacını oluşturarak çalışır. "IQueryable'ı (Of T) genişleten bu yöntemler doğrudan sorgulama yapmaz. Bunun yerine, işlevleri birikimli sorguyu temsil eden bir ifade ağacı olan bir Expression nesnesi oluşturmaktır."
İfade ağaçları, C # ve .NET platformunda çok önemli bir yapıdır. (Genel olarak önemlidirler, ancak C # onları çok kullanışlı hale getirir.) Farkı daha iyi anlamak için, burada resmi C # 5.0 spesifikasyonundaki ifadeler ve ifadeler arasındaki farkları okumayı öneririm . Lamda analizine dalmış ileri teorik kavramlar için ifadeler birinci sınıf nesneler olarak yöntemlere destek sağlar. IQueryable ve IEnumerable arasındaki fark bu noktaya odaklanmıştır. IQueryable ifade ağaçları oluştururken IEnumerable, en azından genel anlamda, Microsoft'un gizli laboratuvarlarında çalışmayanlarımız için değildir.
İşte itme ve çekme perspektifinden farklılıkları ayrıntılarıyla anlatan bir diğer faydalı makale. ("Push" vs. "pull" ile veri akış yönüne atıfta bulunuyorum. .NET ve C # için Reaktif Programlama Teknikleri
Deyim lambdasları ve ifade lambdasları arasındaki farkları detaylandıran ve ifade gerilimi kavramlarını daha derinlemesine tartışan çok iyi bir makale: C # delegelerinin, ifade ağaçlarının ve lambda ifadelerinin lambda ifadelerine karşı yeniden gözden geçirilmesi. ."
Veritabanından alınan verileri kullanmak IEnumerableve IQueryableişlemek için kullanıyoruz . IQueryablemiras alır IEnumerable, IQueryabletüm IEnumerableözellikleri içerir. Arasındaki büyük fark IQueryableve IEnumerableolmasıdırIQueryable , oysa filtrelerle yürütür sorgu IEnumerablesorgu önce ve sonra şartlarına dayalı veriler filtreler çalıştırır.
Aşağıda daha ayrıntılı bir fark bulabilirsiniz:
IEnumerable
IEnumerable içinde var System.Collections adIEnumerable sunucu tarafında bir seçme sorgusu yürütme, bir istemci tarafında bellekte veri yükleme ve ardından verileri filtrelemeIEnumerable Liste, Dizi gibi bellek içi koleksiyonlardaki verileri sorgulamak için uygundurIEnumerable LINQ to Object ve LINQ to XML sorguları için faydalıdırIQueryable
IQueryable içinde var System.Linq adIQueryable tüm filtrelerle sunucu tarafında bir 'seçme sorgusu' yürütürIQueryable bellek dışı (uzak veritabanı, hizmet gibi) koleksiyonlarından veri sorgulamak için uygundurIQueryable LINQ to SQL sorguları için faydalıdırBu yüzden IEnumerablegenellikle bellek içi toplama ile uğraşırken IQueryable, genellikle koleksiyonları manipüle etmek için kullanılır.
Hem IEnumerable hem de IQueryable, bir veri toplamasını tutmak ve veri toplama işlemini filtrelemek için kullanılır. Burada örnekle en iyi fark karşılaştırmasını bulabilirsiniz.
http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html

IQueryable, veritabanından büyük miktarlarda veri ile uğraşırsak IEnumerable'dan daha hızlıdır, çünkü IQueryable, veritabanından gereklilikten bağımsız olarak IEnumerable olarak tüm verileri aldığı veritabanından yalnızca gerekli verileri alır
ienumerable: işlenmemiş bellekle uğraşmak istediğimizde, yani veri bağlantısı olmadan iqueryable: sql sunucusu ile ne zaman uğraşacağız, yani veri bağlantısı ilist: nesne ekleme, nesne silme vb.