2013-03-08 29 views
15

ile kullanın IQueryable.Count en bir IList<T> veya IQueryable<T> ile kullanılabilir sayfalandırmada diyelim bir sınıf düşünün. Bu sınıf, int TotalItems özelliğine sahip olacaktır; bu, (bu şaşırtıcı değil), uygulanabilir veya sayılabilir parametrelerin sayısını alacak/ayarlayacaktır. Count() yöntem olacaktır IEnumerable <T> parametresi

//simplified 
public Pagination(IEnumerable<T> query) 
    { 
     TotalItems = query.Count(); 
    } 

ben parametre olarak IEnumerable<T> kullanırsanız, Enumerable.Count() (Yanlış değilsem , konu bu var). Bu nedenle, sorgu bir IQueryable<T> (IEnumerable<T> öğesinden devralınır) olsa bile, numaralandırılır (bu açıkça bir "db sorgusuyla istenmez").

Yani 2 ctor

//simplified 
public Pagination(IEnumerable<T> query) 
    { 
     TotalItems = query.Count(); 
    } 
public Pagination(IQueryable<T> query) 
    { 
     TotalItems = query.Count(); 
    } 

DÜZENLEME, benim IEnumerable<T> aslında bir IQueryable<T> olduğunda Queryable.Count() yöntemi kullanmak için bir yol yoktur, yoksa bu durumda örneğin, sahip benim tasarımını değiştirmek zorunda yapmak Ben IEnumerable<T> devralan IQueryable<T>IEnumerable<T> ve IQueryable<T> aynı adla uzantısı yöntemlerine sahip olduğu gerçeği ile ilgisi olduğunu anlıyorum ve bu böyle "onlar aynı şeyi benziyor" uzantısı yöntemi için aynı adları, olması güzel, ama bence Hala bazen aynı "mimarisi" ile,

onlar çerçevede, başka örnekler var merak için ...

Jenerik soruyu kafa karıştırıcı: uzatma yöntemleri için kalıtım + ortak isimler?

+0

neden bir "int" yi kabul etmiyor ve sayımın nereden geldiği bir sıralama/sorgu saymasına izin vermiyor? – Servy

+0

@AakashM iyi, bu soru gerçek bir denemeden sonra ve MiniProfiler sonuçlarına bir bakış gelir: Ben kötü bir yorumlama yapmış olabilir, bu durumda, kafamı bir duvara çarptıracağım;) –

+0

@Servy sivri olarak, bu basitleştirilmiş bir durumdur, 'query' parametresini sınıfımdaki diğer amaçlarla kullanmak isteyebilir ve aynı soruna sahip olan (sorun varsa) diğer "paylaşılan" sorgulanabilir veya Enumerable uzantı yöntemlerini çağırmak isteyebilirim. –

cevap

8

Soruda gördüğünüz gibi iki kurucu aşırı yüklenmelisiniz. Bu, IQueryable yöntemlerinin kullanılmasını isteyip istemediği veya IEnumerable yöntemlerinin kullanılmasını sağlar.

birisi yapmak olsaydı:

Pagination pager = new Pagination(query.AsEnumerable()); 

Sonra açıkça nesnesi, bir IEnumearble değil, bir IQueryable olarak işlenecek istiyorum. Belki de Skip ve Take'un sorgu sağlayıcısı tarafından uygulanmadığını biliyorlar ve bu nedenle sayfalandırma başarısız olur ve Linq'den nesnelere dönüştürülmesi gerekir.

İki aşırı yüklenmeye maruz kaldığınızda, sınıfınızın kullanıcısı tarafından bir bellek dizisiyle mi, yoksa bir sorguyla mı uğraşıldığına karar vermek yerine, kendi başına anlamaya çalışmak yerine, bilinçli bir karar vermiş olursunuz.

+0

+1, Atlama/Alma ile sorgu sağlayıcısı tarafından desteklenmeyebilecek iyi bir örnek. – ken2k

+0

+1 ayrıca, farklı sağlayıcılarda uygulanan uzatma yöntemlerinin iyi bir örneğidir. Yakında kabul edildi, sadece bir soru: Ben daha sonra bir IList parametresi tarafından değiştirilen IEnumerable parametresi ile ctor olabileceğimi düşünmüyor musunuz: Sayım() her nasılsa numaralandıracağını bilerek, bu işleri daha net yapar, değil mi? –

1

Eh, yapabileceği:

TotalItems = enumerable.AsQueryable().Count(); 

Bu doğrudan bir yerli Queryable için sorgu-sağlayıcının Count uygulamayı kullanır veya başka bir şekilde (bir EnumerableQuery kullanmak için bazı ek yükü ile) LINQ nesnelere çare olacaktır.

Başka bir çözüm (potansiyel olarak daha verimli): En sorgulanabilir verimli ICollection veya ICollection<T> uygulaması halinde (bazı sorgu sağlayıcıları ile olduğu gibi) Ancak

var queryable = enumerable as IQueryable<T>; 
TotalItems = queryable != null ? queryable.Count() : enumerable.Count(); 

unutmayın, hatta mevcut çözümünüz potansiyel olarak iyi iş olacağını LINQ içindeki optimizasyonlardan dolayı (Count özelliğini mümkün olan yerlerde bu arabirimlerden kullanır). Sizin IList<T> için, bu optimizasyonu her zaman ICollection<T> uyguladığı için kullanacaktır.

+3

Bu, sorunlara neden olabilir. Birisi bir "IQueryable" 'a sahipse ve' AsEnumerable 'olarak adlandırırsa, * istekleri * LINQ-to-object olarak çözümlenmeleri ve sorgu sağlayıcısına karşı sonraki sorgular gerçekleştirmemeleri anlamına gelir. – Servy

+0

@Servy de, gerçekten AsEnumerable() 'ile numaralandırılmış olacak gibi, sorgu sağlayıcısına karşı (tekrar) gerçekleştirilecek mi? IQueryable () .AsEnumerable() ile neler olduğu konusunda net değilim. AsQueryable() '... –

+1

@ RaphaëlAlthaus Hayır, 'AsEnumerable' hiçbir şey numaralandırmıyor, etkili bir şekilde yapmıyor Nesneyi 'IEnumerable' haline getirmekten başka bir şey yoktur. Tam tanım şu şekildedir: • genel statik IEnumerable AsEnumerable (bu IEnumerable kaynağı) {return source;} ' – Servy

İlgili konular