AsQueryable () 'ın amacı nedir?


107

Amacı mı AsQueryable()etrafında bir geçebilir sadece bu yüzden IEnumerablebeklediğinizden yöntemlere IQueryableveya temsil etmek yararlı bir neden yoktur IEnumerableolarak IQueryable? Örneğin, bunun gibi durumlar için mi olması gerekiyor:

IEnumerable<Order> orders = orderRepo.GetAll();

// I don't want to create another method that works on IEnumerable,
// so I convert it here.
CountOrders(orders.AsQueryable());

public static int CountOrders(IQueryable<Order> ordersQuery)
{
    return ordersQuery.Count();
}

Yoksa gerçekten farklı bir şey yapmasını mı sağlıyor:

IEnumerable<Order> orders = orderRepo.GetAll();
IQueryable<Order> ordersQuery = orders.AsQueryable();

IEnumerable<Order> filteredOrders = orders.Where(o => o.CustomerId == 3);
IQueryable<Order> filteredOrdersQuery = ordersQuery.Where(o => o.CustomerId == 3);

// Are these executed in a different way?
int result1 = filteredOrders.Count();
int result2 = filteredOrdersQuery.Count();

Do IQueryableaynı şeyi yapıyor uçları onun idam keresinde bir İfade oluşturmak bu uzatma yönteminin sürümlerini? Benim asıl sorum şu ki, kullanmak için gerçek bir kullanım durumu AsQueryablenedir?

Yanıtlar:


66

Birkaç ana kullanım vardır.

  1. Diğer yanıtlarda belirtildiği gibi, onu bellek içi veri kaynağı kullanarak sorgulanabilir bir veri kaynağıyla dalga geçmek için kullanabilirsiniz, böylece sonunda numaralandırılamayan bir temelde kullanılacak yöntemleri daha kolay test edebilirsiniz IQueryable.

  2. Bellek içi sıralara veya harici veri kaynaklarına uygulanabilecek koleksiyonları işlemek için yardımcı yöntemler yazabilirsiniz. IQueryableTamamen kullanmak için yardım yöntemlerinizi yazarsanız, AsQueryablebunları kullanmak için tüm numaralandırılabilir öğeleri kullanabilirsiniz. Bu, çok genelleştirilmiş yardımcı yöntemlerin iki ayrı sürümünü yazmaktan kaçınmanıza olanak tanır.

  3. IQueryableDaha türetilmiş bir türden ziyade, sorgulanabilir bir derleme zaman türünü değiştirmenize olanak tanır . Etkisinde; Bir üzerinde kullanmak istiyorum IQueryableKullanmak edeceğimi aynı saatlerde AsEnumerablebir de IEnumerable. Uygulayan, IQueryableancak aynı zamanda bir örnek Selectyöntemi olan bir nesneniz olabilir . Durum buysa ve LINQ Selectyöntemini kullanmak istiyorsanız, nesnenin derleme zamanı türünü olarak değiştirmeniz gerekir IQueryable. Sadece AsQueryableçevirebilirsiniz , ancak bir yönteme sahip olarak tür çıkarımından yararlanabilirsiniz. Genel bağımsız değişken listesi karmaşıksa bu daha kullanışlıdır ve genel bağımsız değişkenlerden herhangi birinin anonim tür olması durumunda aslında gereklidir .


Canlanma için teşekkürler. En eksiksiz olduğu için bunu cevap olarak işaretlemek.
Ocelot 20

5
Bunun IQueryable<T>kaynaklandığı göz önüne alındığında, IEnumerable<T>lütfen "numaralandırılamayan tabanlı IQueryable" ile ne demek istediğinizi açıklar mısınız?
Dai

2
@Dai Bu, bir paketten IQueryabledaha fazlası olan IEnumerableve aslında bir IQueryable.
2016

# 1 tam olarak aradığım şeydi. Doğruladığınız için teşekkürler.
one.beat.consumer

12

AsQueryable için sahip olduğum en geçerli durum birim testidir. Diyelim ki şu biraz uydurma örnek var

public interface IWidgetRepository
{
   IQueryable<Widget> Retrieve();
} 

public class WidgetController
{
   public IWidgetRepository WidgetRepository {get; set;}


   public IQueryable<Widget> Get()
   {
      return WidgetRepository.Retrieve();
   }
}

ve denetleyicinin depodan döndürülen sonuçları geri verdiğinden emin olmak için bir birim testi yazmak istiyorum. Şöyle bir şeye benzeyecekti:

[TestMethod]
public void VerifyRepositoryOutputIsReturned()
{    
    var widget1 = new Widget();
    var widget2 = new Widget();
    var listOfWidgets = new List<Widget>() {widget1, widget2};
    var widgetRepository = new Mock<IWidgetRepository>();
    widgetRepository.Setup(r => r.Retrieve())
      .Returns(listOfWidgets.AsQueryable());
    var controller = new WidgetController();
    controller.WidgetRepository = widgetRepository.Object;

    var results = controller.Get();

    Assert.AreEqual(2, results.Count());
    Assert.IsTrue(results.Contains(widget1));
    Assert.IsTrue(results.Contains(widget2));
}

gerçekten, AsQueryable () yönteminin yapmama izin verdiği yerde, bir taklit kurarken derleyiciyi tatmin etmek.

Yine de bunun uygulama kodunda nerede kullanıldığı ilgimi çekiyor.


11

Sanjuro'nun belirttiği gibi, AsQueryable () işlevinin amacı AsQueryable'ı Nesnelere Linq ve Linq To SQL ile Kullanma'da açıklanmaktadır . Makalede özellikle,

Bu, bir varlık üzerinde IQueryable T ve bazı yöntemler dönüş Listesi döndüren belirli yöntemlere sahip olduğunuz gerçek kelime senaryolarında mükemmel avantajlar sunar. Ancak, koleksiyonun T'nin IQueryable'ı veya T'nin IEnumerable'ı olarak döndürülmesine bakılmaksızın, tüm koleksiyona uygulanması gereken iş kuralı filtreniz vardır. koleksiyon IQueryable'ı uygular, aksi takdirde iş filtresini bellekte Linq kullanarak delegelerin uygulanmasını nesneye uygulamak için geri döner.


6

AsQueryable () işlevinin amacı, bu makalede, Nesnelere Linq ve Linq To SQL ile AsQueryable Kullanımı

MSDN Queryable.AsQueryable Metodunun Açıklamalar bölümünden:

Kaynak türü IQueryable uygularsa, AsQueryable (IEnumerable) onu doğrudan döndürür. Aksi takdirde, Queryable içinde olanlar yerine Enumerable'daki eşdeğer sorgu operatörü yöntemlerini çağırarak sorguları yürüten bir IQueryable döndürür.

Bu tam olarak yukarıdaki makalede bahsedilen ve kullanılan şeydir. Örneğinizde, orderRepo.GetAll'ın dönen, IEnumerable veya IQueryable (Linq'den Sql'ye) ne olduğuna bağlıdır. IQueryable döndürürse, Count () yöntemi veritabanında çalıştırılır, aksi takdirde bellekte çalıştırılır. Başvurulan makaledeki örneğe dikkatlice bakın.


3

Arayüz IQueryablealıntı belgeleri:

IQueryable arabirimi, sorgu sağlayıcıları tarafından uygulamaya yöneliktir.

Dolayısıyla, veri işlemini .NET'te sorgulanabilir hale getirmek isteyen biri için, gerekli olmayan bu veri yapısı numaralandırılabilir veya geçerli numaralandırıcıya sahip olabilir .

IEnumeratorbunun yerine veri akışını yinelemek ve işlemek için bir arabirimdir .


Şunu yeniden ifade etmek ister misiniz: "gerekli olmayan veri yapısı numaralandırılabilir veya geçerli numaralandırıcıya sahip olabilir". Ben arasındaki farkı anlamak IQueryableve IEnumerableama için kullanım örneğini anlamıyorum AsQueryableuzatma yöntemiyle. Yine de bu cümleye biraz takılıyorum, aradığım cevabı bulabileceğinden şüpheleniyorum (olumlu oylara dayanarak).
Ocelot20

Ocelot20 @: ortalama şapka veri tipleri de sağlayıcı tarafından sunulan bu uygular IQueryable o olabilir bir numaralandırma cappability sağlamaz. Sağlayıcıya kalmış. Alıntı belgesi: "Numaralandırılabilir sonuçlar döndürmeyen sorgular, Execute yöntemi çağrıldığında yürütülür."
Tigran

Belki bariz bir şeyi kaçırıyorum, ancak "neden kullanmam gerek AsQueryable()?" Sorusunun yanıtını hala göremiyorum. Bir IEnumerable ile başlıyorsam (zaten bir numaralandırma özelliği sağlayabilen bir şey), neden IQueryableuzantı yöntemini kullanmaya dönüştürmem gerekiyor AsQueryable()? Belki bunun işe yarayacağını gösteren küçük bir kod örneği? Açıklamanda bir şey eksik gibi görünüyor. Zaman ayırdığınız için teşekkürler.
Ocelot20

@ Ocelot20: farkı gerçekten göstermek için sorgu sağlayıcı yazmam gerekiyor. Sen bizim biliyoruz linq to sql, linq to xmlyazma istiyorsanız .. bu yüzden ve linqsürücü hedefleri olduğunu da veri strucutres ( linq to your datasizin API kullanıcıları çalıştırmak için bir imkanı olacaktır böylece), linqkarşı sorgu sizin veri yapıları, sen seçmek zorundaIQueryable
Tigran

2
IQueryableVe arasındaki farkı açıklıyor gibisin IEnumerable. Farkı biliyorum ve istediğim bu değil. Birisinin neden uygulayan bir şeyi alıp IEnumerableonu genişletme yöntemini IQueryablekullanarak dönüştürmek isteyeceğini soruyorum AsQueryable. Cevap verdiğin bu mu? Hala söyleyemiyorum ..
Ocelot20
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.