2010-12-10 7 views
0

Silverlight 4 App WCF RIA ServicesLINQ Leistungsproblem: Summe dauert länger mit weniger Datensätze

Ich habe eine Seite mit einem ComboBox und einem TabControl. Jedes TabItem verfügt über eine Benutzersteuerung, die ein RAD-Chart-Steuerelement anzeigt. Die ComboBox enthält Elemente, die zum Filtern der Daten verwendet werden, die die Benutzersteuerelemente in den Diagrammen anzeigen. Wenn sich die ComboBox-Auswahl ändert, aktualisiert die Seite eine Auflistung von Entitäten, die in einer Eigenschaft einer Instanz/Singleton-Klasse enthalten sind. Die Benutzersteuerelemente werden über die Änderung benachrichtigt, und sie greifen auf die aktualisierte Auflistung von Entitäten zu, die dem Diagrammsteuerelement übergeben werden. Es funktioniert alles. Wenn sich die ComboBox-Auswahl ändert, zeigen die Benutzersteuerelemente eine Teilmenge der ausgewählten Daten basierend auf dem ausgewählten ComboBox-Element an.

Was mich verwirrt hat, ist die Zeit, die es dauert, die Entitätssammlung zu durchlaufen, während die Werte vorbereitet werden, die der Diagrammsteuerung übergeben werden. Das Diagramm zeigt 12 Datenmonate an, sodass ich die Sammlung 12 Mal wiederhole und eine LINQ-Abfrage verwende, um eine Summe für eine Eigenschaft der Objekte in der Sammlung zu erhalten. Ich habe das Performance-Problem auf die einzelne LINQ-Abfrage isoliert, dass die Summe führt:

Decimal sum = myCollection.Where(m => m.CreationDate.Month == month).Sum(m => (m.SalePrice ?? 0)); 

Die einzige Zeile Code manchmal mehr als eine Sekunde dauern kann ausgeführt werden. Das ist nicht schlimm, aber ich wiederhole 12 Monate, so dass die Codezeile 12 Mal ausgeführt wird. Hier

ist der Kicker ...

Die obere ComboBox Option ist 'alle Datensätze'. In meinem Testbeispiel wird also zum ersten Mal, wenn die obige Codezeile verwendet wird, um eine "Summe" zu erhalten, die Sammlung mehr als 500 Datensätze enthalten. Es gibt die Summe in .2 Sekunden zurück. Ich ändere die ComboBox in eine Auswahl, die die Ergebnisse filtert, so dass die Sammlung nur 80 Datensätze enthält. Wohlgemerkt, es handelt sich nicht um völlig unterschiedliche Datensätze, sondern nur um eine Untergruppe der 500, die ein anderes Kriterium erfüllen. Die obige Codezeile benötigt 1,2 Sekunden zum Ausführen. Wenn ich nach einer Summe von mehr als 500 Datensätzen frage, dauert es 0,2 Sekunden. Wenn ich nach einer Summe von 80 Datensätzen frage, dauert es 1,2 Sekunden.

Was könnte das verursachen?

Danke,

Antwort

2

Wie filtern Sie, um die Teilmenge zu erstellen? Ist "Collection" eine Linq-Abfrage selbst, die bei der Ausführung bis zu dieser Zeile angezeigt wird? Wenn dies der Fall ist, könnte die Geschwindigkeitsdifferenz, die Sie sehen, die Anwendung der Filterlogik sein.

Eine allgemeine Möglichkeit, dies schneller zu machen, wäre die Berechnung aller 12 Zahlen in einem einzigen Durchgang. Das ist einfach genug mit dem GroupBy Linq Operator:

var AllSums = Collection.GroupBy(m=>m.CreationData.Month).ToDictionary(g => g.Key, g => g.Sum(m => m.SalePrice ?? 0)); 
var JanuarySum = AllSums[January]; 

Dies sollte 12 völlig separate Schleifen übertreffen.

Edit: Hier ist eine gute Beschreibung der latenten Ausführung: Linq and Deferred Execution

+0

Ich nenne es eine Teilmenge, weil ich, dass es betonen will, ist nicht eine völlig andere 80 Datensätze, sondern nur 80 Datensätze aus den ursprünglichen 500 Ich sehe, was Sie meinen, durch das Potential des Filters, der bis zur Ausführung dieser Zeile zurückgestellt wird. Hier hört mein LINQ-Verständnis auf. Wenn ich einen Count() für die Sammlung mache (wie ich vor der eingefügten Zeile oben bin), und es 80 Datensätze aufzeichnet, wird derselbe Filter jedes Mal erneut ausgeführt, wenn ich gegen die Sammlung summiere? – Roger

+0

Uhg .. halten Sie die Eingabetaste gedrückt, bevor ich fertig bin mit der Eingabe meines Kommentars ... Um die Sammlung zu erstellen, erstelle ich ein neues IEnumerable und setze es gleich einem anderen collecion.Where (... und ein paar anderen where-Klauseln .Hat diese neue Instanz einer Sammlung möglicherweise eine verzögerte Ausführung in den where-Klauseln? Wenn die Abfrage zum ersten Mal abgefragt wird, wird sie jedes Mal zurückgestellt, wenn Sie sie abfragen. Danke ... Und ich werde Ihre GroupBy-Klausel ausprobieren, nachdem ich das Perf-Problem verstanden habe. – Roger

+0

Wenn ich eine neue Sammlung erstellen und sie mit einer LINQ-Abfrage aus einer anderen Sammlung befüllen soll, gibt es dann Bedenken hinsichtlich der Ausführungsausführung bei der neuen Sammlung? – Roger