2016-10-19 5 views
0

In meiner Datenbank habe ich viele Kunden und ich sende jeden Kunden Bestellungen. Jetzt muss ich alle Kunden durchlaufen und finde die Kunden, die mehr als einen Zielpreis haben. Ich verwende dieses Stück Code:Schnellste Methode Berechnung der Summe der Kundenaufträge mit Linq

List<int> IDz = new List<int>(); 
foreach (var customer in db.tblCustomers) 
{ 
    total = 0; 
    foreach (var order in db.tblCustomerOrders.Where(x => x.CustomerID == customer.CustomerID)) 
     total += Convert.ToDouble(order.Amount); 

    if (total >= Convert.ToDouble(txtAmount.Text)) 
     IDz.Add(customer.CustomerID); 
} 

Dieser Code dauert etwa 15 Sekunden für etwa 1500 Kunden. Wie kann ich schneller machen? irgendein Vorschlag?

+0

Wahrscheinlich überprüfen Sie Ihre db zu bekommen und einen Index erstellen für CustomerID in Ihren Auftragstabellen. – mybirthname

+1

Linq macht es nicht "besser" oder sogar "schneller" wie Sie wollen, es ist nur syntaktischer Zucker. Um die Leistung zu erhöhen, sollten Sie zuerst einen Profiler verwenden, um zu überprüfen, ob Ihre Performance-Probleme wirklich mit diesem Code zusammenhängen und * ob * sie die Datenbank so konfigurieren möchten, wie es von meinem Geburtsnamen vorgeschlagen wird. Das Problem bei LINQ ist, dass es genau das selbe intern erledigt, wie Sie es bereits tun - das Schleifen Ihrer Zeilen, die von Ihrer Datenbank zurückgegeben werden. – HimBromBeere

+2

Speichern numerischer Werte als Strings ... Ich denke, Code zahlt dich nur für solch ein interessantes Design zurück :) - [stringly typed code] (https://blog.codinghorror.com/new-programming-jargon/) ... Bitte klären Sie, warum Sie dies tun müssen (insbesondere beim Vergleich von "Summe") und warum Sie nicht alle Operationen in DB durchführen. –

Antwort

4

Zunächst einmal, wie Sie CustomerID und Amount Spalten in tblCustomerOrders haben, gibt es keine Notwendigkeit, eine Schleife durch tblCustomers. Was Sie tun müssen, ist die Gruppe tblCustomerOrders nach CusotmerID, finden Sie die Gesamtsumme und überprüfen Sie, ob der Betrag mehr als die Eingabemenge ist, wählen Sie dann CustomerID s, die diese Kriterien erfüllt. Da Sie all diese Dinge auf Datenbankseite tun (ich glaube, dass Sie EntityFramework verwenden), muss Ihre Abfrage viel schneller sein.

double inputAmount = Convert.ToDouble(txtAmount.Text); 
var result = db.tblCustomerOrders 
    .GroupBy(m => m.CustomerID) 
    .Select(g => new 
    { 
     CustomerID = g.Key, 
     Sum = g.Sum(m => m.Amount) 
    }) 
    .Where(m => m.Sum > inputAmount) 
    .Select(m => m.CustomerID) 
    .ToList(); 
+1

Ihr Code wird nicht funktionieren - Sie wählen "CustomerID" und "Sum", aber in "Where" -Klausel beziehen Sie sich auf "Amount", die nicht da sein wird, seit Sie etwas anderes ausgewählt haben. Ich denke, Ihre 'Where' -Klausel sollte so aussehen:' Where (m => m.Sum> inputAmount) ' –

+0

@ PawełHemperek, danke, dass Sie darauf hingewiesen haben, –

+0

@Stranger, kein Problem dort auch, nur fügen Sie, was Sie Filter vor' GroupBy' Methode mit 'When' Methode –

2

können Sie unter Ansatz versuchen, für den Gesamtbetrag der Berechnung:

double total = db.tblCustomerOrders.Where(x => x.CustomerID == customer.CustomerID).Select(t => t.Amount ?? 0).Sum(); 

die Null-Koaleszenz-Operator werden Sie einen Standardwert von 0 geben, wenn t.Amount null ist.

Hoffe, es wird Ihnen helfen, Dank

2

Versuchen Sie dies, wird die Abfragezeit verkürzen, indem Sie ohne die Berechnung in der Abfrage tun, um die Kunden an erster Stelle

double amnt = Convert.ToDouble(txtAmount.Text); 
 
List<int> IDz = db.tblCustomers.Where(c => db.tblCustomerOrders.Where(o => o.CustomerID == c.CustomerID).Sum(o => o.Amount) > amnt).Select(c => c.CustomerID).ToList();

Verwandte Themen