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 IQueryable
sı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 IQueryable
arabirimi uygularsa geri döndürür , aksi takdirde ConstantExpression
döndürülen bir EnumerableQuery
nesnede 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:
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 IQueryable
gelen arayüz devralır IEnumerable
, her neyse IEnumerable
yapabilir, IQueryable
ayrıca yapabilirsiniz.
Birçok fark var ama en büyük farkı yaratan tek büyük fark hakkında konuşalım. IEnumerable
arayüzü, koleksiyonunuz kullanılarak yüklendiğinde kullanışlıdır.LINQ
veya Entity framework ve koleksiyona filtre uygulamak istediğinizde .
IEnumerable
Varlık çerçevesi ile birlikte kullanılan aşağıdaki basit kodu göz önünde bulundurun . Bir kullanıyor Where
olan kayıtları almak için filtre EmpId
olduğunu 2
.
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Bu, filtrenin IEnumerable
kodun 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 EmpId
olduğunu 2
.
Ama şimdi değişti aşağıdaki kodu görmek IEnumerable
iç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 IQueryable
veIEnumerable
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 IEnumerable
iyi 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 Employee
veritabanındaki tablodan en iyi 2 kaydı almaktı. Konsol uygulamama Employee
veritabanı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 IQueryable
uygulamak 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 IEnumerable
5 kaydın tümünü getirildi Salary
ve 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 IEnumerable
ve IQueryable
işlemek için kullanıyoruz . IQueryable
miras alır IEnumerable
, IQueryable
tüm IEnumerable
özellikleri içerir. Arasındaki büyük fark IQueryable
ve IEnumerable
olmasıdırIQueryable
, oysa filtrelerle yürütür sorgu IEnumerable
sorgu ö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 IEnumerable
genellikle 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.