SORU
31 Temmuz 2013, ÇARŞAMBA


'fark(s) arasında ne .() ToList, .() AsEnumerable, AsQueryable()?

İlk uygular ve ikinci uygular IQueryable ve IEnumerable hangi L2E L2O bazı diefferences biliyorum ve Q benim kapsamı EF 5 içinde.

Benim Q teknik farkı(ler) Bu 3 yöntemleri. Birçok durumda hepsi çalışıyormuşsunuz. Ben de onlara kombinasyonları kullanarak .ToList().AsQueryable() gibi görüyor.

1) Bu yöntem tam olarak ne demek?

2) başkaları ile karşılaştırıldığında, onlar hakkında herhangi bir performans ya da başka bir sorunu var mı?

Neden 3) örneğin .AsQueryable() yerine .ToList().AsQueryable()?

Şimdiden teşekkürler

CEVAP
1 AĞUSTOS 2013, PERŞEMBE


Bu konuda söylenecek çok şey var. Beni AsEnumerable AsQueryable odaklanalım ve yol boyunca ToList() söz.

Bu yöntemler ne yaparsınız?

AsEnumerable AsQueryable IEnumerable dökme dönüştürmek veya 23**, sırasıyla. Derimcast veya convertbir nedeni:

  • Kaynak Hedef arabirimini uygulayan nesne, kaynak ama döndürülen nesnesidökmehedef arabirimi. Diğer bir deyişle: türü değişmez, ancak derleme zamanı türüdür.

  • Kaynak nesneyi hedef arabirim uygulamıyor, kaynak nesnedönüştürülmüşhedef arabirimi uygulayan bir nesne haline. Her iki türü ve derleme türü değişti.

Bana bir örnek ile bunu gösterelim. Derleme zamanı tür ve (courtesy Jon Skeet) bir nesnenin gerçek türü raporlar küçük bir yöntem var:

void ReportTypeProperties<T>(T obj)
{
    Console.WriteLine("Compile-time type: {0}", typeof(T).Name);
    Console.WriteLine("Actual type: {0}", obj.GetType().Name);
}

Hadi rasgele bir seri-to-sql IQueryable uygulayan Table<T>, deneyin:

ReportTypeProperties(context.Observations);
ReportTypeProperties(context.Observations.AsEnumerable());
ReportTypeProperties(context.Observations.AsQueryable());

Sonuç:

Compile-time type: Table`1
Actual type: Table`1

Compile-time type: IEnumerable`1
Actual type: Table`1

Compile-time type: IQueryable`1
Actual type: Table`1

Sınıfın hep döndü kendisi olduğunu görürsünüz, ama onun temsil değiştirir.

Şimdi IEnumerable, IQueryable uygulayan bir nesne:

var ints = new[] { 1, 2 };
ReportTypeProperties(ints);
ReportTypeProperties(ints.AsEnumerable());
ReportTypeProperties(ints.AsQueryable());

Sonuçları:

Compile-time type: Int32[]
Actual type: Int32[]

Compile-time type: IEnumerable`1
Actual type: Int32[]

Compile-time type: IQueryable`1
Actual type: EnumerableQuery`1

İşte orada. AsQueryable() bir dizi "IQueryable<T> veri kaynağı olarak IEnumerable<T> bir topluluğu temsil eder." EnumerableQuery, dönüştürdü (MSDN).

Ne işe yarar?

AsEnumerableçoğunlukla eski L2O olan fonksiyonları desteklemiyor çünkü nesneleri (L2O) bu SERİ için IQueryable herhangi bir uygulamadan geçiş yapmak için kullanılır. Daha fazla bilgi için bkz: What is the effect of AsEnumerable() on a LINQ Entity?.

Varlık Çerçevesi sorgusu örneğin, yalnızca yöntemlerinin sınırlı sayıda kullanabiliriz. Eğer öyleyse, örneğin, genellikle gibi bir şey yazmak istiyoruz sorguda kendi yöntemleri kullanmamız gerekiyor

var query = context.Observations.Select(o => o.Id)
                   .AsEnumerable().Select(x => MySuperSmartMethod(x))

ToListIEnumerable<T> List<T> – genellikle bu amaç için kullanılır. bir dönüştüren – ToList vs AsEnumerable kullanmanın avantajı AsEnumerable sorgu yürütmek değil. AsEnumerable ertelenmiş yürütme korur ve genellikle işe yaramaz Ara bir liste oluşturmak değil.

SERİ bir sorgu zorla çalıştırma istenilen diğer taraftan,, ToList bunu yapmak için bir yol olabilir.

AsQueryablesayısız bir koleksiyon yapmak için kullanılabilir ETMENİZ ifadeleri ifadeleri kabul edin. Daha fazla bilgi için buraya bakınız: Do i really need use AsQueryable() on collection?.

Madde kullanımı ile ilgili not!

AsEnumerable bir ilaç gibi çalışır. Hızlı bir düzeltme, ama hiç bir maliyet ve altta yatan sorunu çözmek değil.

Taşma cevaplar Yığını, insanlar AsEnumerable SERİ ifadelerde desteklenmeyen bir yöntem ile herhangi bir sorunu çözmek için uygulama görüyorum. Ama fiyat her zaman açık değildir. Eğer bunu yaparsanız, örneğin, bu:

context.MyLongWideTable // A table with many records and columns
       .Where(x => x.Type == "type")
       .Select(x => new { x.Name, x.CreateDate })

...her şey düzenli bir şekilde SQL deyimi çevrilirfiltreler(Where)projeler(Select). Diğer bir deyişle, SQL sonuç kümesi uzunluğu ve genişliği her ikisi de, sırasıyla, azalır.

Artık kullanıcılar sadece tarih CreateDate parçası görmek istediğinizi varsayalım. Varlık Çerçevesi içinde hızlı bir şekilde keşfedeceksiniz...

.Select(x => new { x.Name, x.CreateDate.Date })

...desteklenen (yazma anda). Ah, neyse ki AsEnumerable düzeltme var:

context.MyLongWideTable.AsEnumerable()
       .Where(x => x.Type == "type")
       .Select(x => new { x.Name, x.CreateDate.Date })

Tabii, muhtemelen çalışır. Ama belleğe tüm masa çeker ve daha sonra filtre ve tahminler geçerlidir. Çoğu insan Where ilk yapmak için yeterince akıllı

context.MyLongWideTable
       .Where(x => x.Type == "type").AsEnumerable()
       .Select(x => new { x.Name, x.CreateDate.Date })

Ama yine de tüm sütunları ilk getirilen ve projeksiyon bellekte yapılır.

Gerçek düzeltme:

context.MyLongWideTable
       .Where(x => x.Type == "type")
       .Select(x => new { x.Name, DbFunctions.TruncateTime(x.CreateDate) })

(Ama bu biraz daha fazla bilgi gerektirir...)

Bu yöntemler ne?

Şimdi önemli bir uyarı. Ne zaman

context.Observations.AsEnumerable()
                    .AsQueryable()

kaynak IQueryable olarak temsil edilen nesne ile sona erecek. Her iki yöntem de sadece cast ve convert yok çünkü).

Ama ne zaman

context.Observations.AsEnumerable().Select(x => x)
                    .AsQueryable()

sonuç ne olur?

Select WhereSelectEnumerableIterator üretir. Bu bir iç .Net sınıf IEnumerable uygular67 ** değil. Başka tür bir dönüşüm gerçekleşmiş ve AsQueryable sonraki asıl kaynağı artık dönebilirsiniz.

Bu ima AsQueryable kullanaraksihirli bir şekilde değil enjekte sorgu sağlayıcısıbir sayısız içine kendine has özellikleri ile. Sanırım öyle

var query = context.Observations.Select(o => o.Id)
                   .AsEnumerable().Select(x => x.ToString())
                   .AsQueryable()
                   .Where(...)

Burada durum hiç SQL tercüme edilecektir. AsEnumerable() SERİ açıklamaları ardından kesin olarak varlık çerçevesi sorgu kuruluşu ile bağlantıyı keser.

Ben mesela kişi '' AsQueryable çağırarak. bir koleksiyon Include yetenekler kazandırmak için çabaladığımız burada soruları gördüm çünkü kasıtlı olarak bu örnek göster Derler ve çalıştırır, ama temel nesne Include uygulaması artık yok, çünkü hiçbir şey yapmaz.

Belirli Uygulamaları

Şimdiye kadar, bu sadece Queryable.AsQueryable ve Enumerable.AsEnumerable uzatma yöntemleri hakkında. Ama tabii ki herkes aynı adı taşıyan örnek yöntemleri veya uzatma yöntemleri (fonksiyonlar) yazabilirsiniz.

Aslında AsEnumerable uzantısı belirli bir yöntemin yaygın bir örnek DataTableExtensions.AsEnumerable. DataTable düzenli uzatma yöntemleri uygulamak yok IQueryable veya* *81, uygulamıyor.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • CNET

    CNET

    5 Mayıs 2006
  • DavidParody

    DavidParody

    17 EKİM 2009
  • steven johns

    steven johns

    11 Mart 2011