2016-04-05 99 views
0

Bu kod, en çok rapor edilen beş üst düzey seroiti bir patojende sıralamaya çalışıyorum. Bildirilebilecek 800'den fazla serotip olduğunu varsayalım. Verilen patojen için tüm raporları tutan bir ObjectQuery ile başladım. (Hepsi değilse)Filtreleme ve sıralama verilerini optimize etmek için linq'e daha iyi nasıl taşınır?

Dictionary<string, int> unsorted = new Dictionary<string, int>(); 

//'serotypes' is an objectquery of 800+ serotypes 
foreach (LookupSerotype serotype in serotypes) 
{ 
    var count = Reports.Count(r => r.serotypeId == serotype.serotypeId); 
    unsorted.Add(serotype.serotypeName, count); 
} 

// convert to list in memory in order to sort the data 
var sorted = unsorted.ToList(); 

sorted.Sort(delegate(KeyValuePair<string, int> first, KeyValuePair<string, int> next) 
{ 
    return first.Value.CompareTo(next.Value); 
}); 

// reverse because the largest were sorted to the bottom 
sorted.Reverse(); 

Ben en çok dönüştürebilir miyim bu daha linq için: Şimdi her serotip göre gruplandırılmış raporların sayısını saymak ve bu Ben şimdi yazdım nasıl üst 5. geri çekmek gerekir Bu hesaplamaların db'ye sorgulanması için sql'ye mi? Veya bu bilgiyi tamamen almak için daha hızlı/daha iyi bir yol var mı?

Özellikle başında ilk foreach döngüsü uzun sürer ve LINQ ile bunu istiyorum ben

+0

"LookupSerotypes" (bir "DbSet") gibi bir özelliğe sahip bir bağlam olduğunu varsayabiliriz. Bu arada, 'ObjectQuery', linq-to-sql değil, framework çerçevesine sahiptir. –

+0

Evet, üzgünüz, bu bir varlık çerçeve nesnesi bağlamıdır. Ve sanırım db'nin sorgusu için EF'den Linq-to-Sql'e gidecekti. –

cevap

1

serotypes veederseEF IQueryable ler vardır ve serotype.serotypeId varsayarak PK (benzersiz), o zaman böyle group join dayalı tek EF sorgusu kullanabilirsiniz geçerli:

var query = 
    (from st in serotypes 
    join r in Reports on st.serotypeId equals r.serotypeId into stReports 
    order by st.serotypeName descending 
    select new { st.serotypeName, reportCount = stReports.Count() } 
    ).Take(5); 

var result = query 
    .AsEnumerable() // switch to LINQ to Objects context 
    .Select(e => new KeyValuePair<string, int>(e.serotypeName, e.reportCount)) 
    .ToList(); 

sadece zor kısmı LINQ geçmek için ihtiyaçtır bağlamı Nesneleri Son projeksiyondan önce, EF projeksiyon (select) sınıf/yapı parametresiz kurucuya desteklemiyor.

1

ile yardım kullanabilirsiniz, bu size yakın olsun olmalıdır: Ayrıca

var topFive = serotypes.GroupBy(s => s.serotypeName) 
     .Select(s => new 
     { 
      SeroTypeName = s.serotypeName, 
      Total = s.Count() 
     } 
     .OrderByDescending() 
     .Take(5) 
     .ToList(); 

bir sorgu aracılığıyla sunucu üzerinde bazı iş yapmak istiyorsanız, bu SQL kullanabilirsiniz:

Select Top 5 serotype.serotypeName, Count(*) as Total 
    from serotype 
group by serotype.serotypeName 
order by Total Desc