2016-04-05 11 views
0

Ich habe diesen Code, wo ich versuche, die Top fünf am häufigsten berichteten Serotypen in einem Erreger zu sortieren. Nehmen wir an, es gibt über 800 Serotypen, die möglicherweise gemeldet werden könnten. Ich beginne mit einer ObjectQuery, die alle Berichte für diesen bestimmten Erreger enthält. Ich brauche jetzt die Anzahl der Berichte von jedem Serotyp gruppiert zählen und die Top-5 zurückziehen Das ist, wie ich es jetzt geschrieben haben:Wie kann man linq zu SQL besser nutzen, um Filter- und Sortierdaten zu optimieren?

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(); 

Kann ich die meisten konvertieren (wenn nicht alle) dieser zu mehr Linq zu SQL, um diese Berechnungen in der Abfrage zur DB zu haben? Oder gibt es einen schnelleren/besseren Weg, diese Informationen vollständig zu nutzen?

Insbesondere die erste foreach-Schleife am Anfang nimmt die längste und ich Hilfe bei

+0

Können wir annehmen, dass es einen Kontext mit einer Eigenschaft wie 'LookupSerotypes' (ein' DbSet') gibt. "ObjectQuery" ist übrigens nicht linq-to-sql, sondern ein Entity-Framework. –

+0

Ja, tut mir leid, Sie haben Recht, es ist ein Entity Framework Objekt Kontext. Und ich denke, es würde durch EF nicht Linq-zu-Sql für die Abfrage an die db gehen. –

Antwort

1

wenn serotypes und: wenn Sie einen Teil der Arbeit auf dem Server über eine Abfrage tun möchten, können Sie diese SQL verwendensind EF IQueryable s, und serotype.serotypeId ist unter der Annahme, PK (einzigartig), dann können Sie eine einzelne EF-Abfrage auf group join wie diese Basis nutzen:

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(); 

Der einzige schwierige Teil die Notwendigkeit, LINQ zu wechseln ist auf Objekte Kontext vor der endgültigen Projektion, weil EF keine Projektion (select) für den parameterlosen Konstruktor class/struct w/o unterstützt.

1

verwenden könnte Wenn Sie dies mit LINQ tun möchte, sollte dies Sie nahe kommen:

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

Auch

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