Laden...

Performance verbessern

Erstellt von tristar vor einem Jahr Letzter Beitrag vor einem Jahr 578 Views
T
tristar Themenstarter:in
98 Beiträge seit 2016
vor einem Jahr
Performance verbessern

Hallo zusammen, ich fülle eine DataGridview und möchte anschließend zwei Spalten farbig markieren.
Soweit klappt das auch alles. Der Aufruf zum Laden/Anzeigen der Daten geht richtig schnell, nur die farbliche Markierung dauert recht lange (~10sek).
Nun wäre meine Frage, ob ein anderer Aufbau zu einer Verbesserung der Performance führt? Bzw. was ich ändern kann/soll?


dataGridView1.DataSource = dt;

Die farbliche Markierung:


void ColorGridView()
        {
            bool weKomplettAbgeschlossen = false;
            bool weTeilweiseAbgeschlossen = false;
            bool reKomplettAbgeschlossen = false;
            bool reTeilweiseAbgeschlossen = false;

            for (int n = 0; n < dataGridView1.Rows.Count; n++)
            {
                // Prüfen ob WEbereits komplett abgeschlossen wurde.
                weKomplettAbgeschlossen = AufrufWE_Abgeschlossen_Pruefen(Convert.ToInt32(dataGridView1["id", n].Value));
                if (!weKomplettAbgeschlossen)
                {
                    weTeilweiseAbgeschlossen = AufrufWE_Erfolgt(Convert.ToInt32(dataGridView1["id", n].Value));
                    if (weTeilweiseAbgeschlossen)
                    {
                        dataGridView1["WEabgeschlossen", n].Style.BackColor = System.Drawing.Color.Yellow;
                    }
                    if (!weTeilweiseAbgeschlossen)
                    {
                        dataGridView1["WEabgeschlossen", n].Style.BackColor = System.Drawing.Color.Red;
                    }
                }
                if (weKomplettAbgeschlossen)
                {
                    dataGridView1["WEabgeschlossen", n].Style.BackColor = System.Drawing.Color.Green;
                }

                // Prüfen RE komplett abgeschlossen.
                reKomplettAbgeschlossen = AufrufRE_Abgeschlossen_Pruefen(Convert.ToInt32(dataGridView1["id", n].Value));
                if (!reKomplettAbgeschlossen)
                {
                    reTeilweiseAbgeschlossen = AufrufRE_Erfolgt(Convert.ToInt32(dataGridView1["id", n].Value));
                    if (reTeilweiseAbgeschlossen)
                    {
                        dataGridView1["REabgeschlossen", n].Style.BackColor = System.Drawing.Color.Yellow;
                    }
                    if (!reTeilweiseAbgeschlossen)
                    {
                        dataGridView1["REabgeschlossen", n].Style.BackColor = System.Drawing.Color.Red;
                    }
                }
                if (reKomplettAbgeschlossen)
                {
                    dataGridView1["REabgeschlossen", n].Style.BackColor = System.Drawing.Color.Green;
                }
            }
        }


Hier mal der Aufruf AufrufWE_Erfolgt:


 public static bool AufrufWE_Erfolgt(int id)
        {
            try
            {
                using (entity ctx = new entity())
                {
                    var query = (from w in ctx.tblwareneingang
                                 where w.bestellId == id
                                 select w).ToList();

                    if (query != null)
                    {
                        foreach (tblwareneingang we in query)
                        {
                            // falls abgeschlossen.
                            if (we.liefermengeAbgeschlossen)
                                return true;
                            else
                                // falls zumindest Eintrag existiert.
                                if (we.gelieferteMenge != 0)
                                    return true;
                        }
                        return false;
                    }
                    else
                        return false;
                }
            }
            catch (Exception ex)
            {
                return false; ;
            }
        }

16.774 Beiträge seit 2008
vor einem Jahr

Der Code ist im Endeffekt das, was man weitläufig Spaghetti-Code nennt.
Daher ja: da kann man enorm viel verbessern.

Enorm fressen wird der Datenbank Code. Da ist quasi alles falsch, was man falsch machen kann 🙂

  • Die statische Methode wird dauern aufgerufen
  • Ständig neue DB Connection
  • Ständig Queries mit hoher Materialisierungsleistung

Im Endeffekt vollständig Code neu schreiben:

  • Trennung von DB und UI Code -> [Artikel] Drei-Schichten-Architektur
  • Connection Sharing, Repository Pattern
  • Daten in einem Rutsch holen, nicht in n
  • Die statische Methode hier ist ganz klassisch eine Fehlprogrammierung

Das sollte das ganze um 99+% verbessern und in wenigen Millisekunden durchlaufen.

T
tristar Themenstarter:in
98 Beiträge seit 2016
vor einem Jahr

@Abt danke für deine Hilfe!
Ich werde mich mal an die Überarbeitung machen ...

  • Daten in einem Rutsch holen, nicht in n

Verstehe zwar was du damit meinst, aber wie soll es in einem Rutsch gehen? Die Daten schon beim ersten Abruf mit übergeben?
Sonst kann ich doch nur zeilenweise prüfen?!

16.774 Beiträge seit 2008
vor einem Jahr
  • Alle Daten aus dem Grid ermitteln
  • DB Query ausführen
  • Resultat auf das Grid anwenden

Das bekommt man fast geschenkt, wenn man Datenbindung verwendet 🙂Bind data to DataGridView Control - Windows Forms .NET Framework

T
2.216 Beiträge seit 2008
vor einem Jahr

Du könntest deine Abfrage auch durch ein Dictioanry mit der ID als Key und dem Bool als Value umstellen.
Dazu müsstest du alle Daten vorladen und pro ID aus den Daten dann deine Logik zur Prüfung durchführen.
Dann kannst du einfach mit TryGetValue den Bool Wert ermitteln.
Gibt TryGetValue zurück, müsst du dann nur den Fall wie bei einem false verarbeiten.

Dadurch sparst du dir auch die Einzelabfragen, die am meisten Performance kosten.
Ansonsten ist der Code, wie Abt auch schon schrieb, stark verbesserungswürdig.
Alleine deine if Verzweigungen mit Negierung sind einfach else Blöcke.
Aber auch die anderen Anmerkungen von Abt sollest du beachten um den Code in Nahe Zukunft noch sinnvoll warten zu können.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

M
366 Beiträge seit 2006
vor einem Jahr

..und noch eine Vorgehensweise (die beim Laden von Internetseiten Sinn haben kann): erst das Control überhaupt darstellen lassen, danach in der gewünschten Formatierung.

Goalkicker.com // DNC Magazine for .NET Developers // .NET Blogs zum Folgen
Software is like cathedrals: first we build them, then we pray 😉

T
tristar Themenstarter:in
98 Beiträge seit 2016
vor einem Jahr

Die statische Methode sieht nun so aus:


...
foreach (var item in lst)
                    {
                        var query = (from w in ctx.tblwareneingang
                                     where w.Id == item
                                     select new EinkaufDaten
                                     {
                                         Id = (int)w.bestellungen_ekId,
                                         LiefermengeAbgeschlossen = w.liefermengeAbgeschlossen,
                                         GelieferteMenge = (int)w.gelieferteMenge
                                     }).ToList();

                        lstDaten.AddRange(query);
                    }
                    return lstDaten;
...

Ich habe nun die Methode ColorGridView wie folgt umgebaut.


 void ColorGridView(DataGridView dg, List<string> lst)
        {

List<EinkaufDaten> lstDaten = DB.WE_Erfolgt(lst);
            foreach (var item in lstDaten)
            {
                foreach (DataGridViewRow row in dg.Rows)
                {
                    if (row.Cells["id"].Value.ToString() == item.IdEK.ToString())
                    {
                        if ((item.MengeAbgeschlossen == true) || (item.GelieferteMenge > 0))
                        { 
                            row.Cells["WEabgeschlossen"].Style.BackColor = System.Drawing.Color.Yellow; 
                        }
                        else
                        { row.Cells["WEabgeschlossen"].Style.BackColor = System.Drawing.Color.Red; }
                    }
                }

Hoffe, dass dies nun zumindest etwas besser ist?!
Abruf der Daten erfolgt nur einmalig über DB.WE_Erfolgt.

Momentan ist es auch deutlich schneller. Es wird auch farblich markiert, aber der else Zweig für dir rote Farbe wird nie
ausgeführt. Weshalb?

16.774 Beiträge seit 2008
vor einem Jahr

Naja, aus unserer Sicht stellt sich die Frage, was Du hören willst.

Die "So programmiert man halt in Objektorientierten Sprachen / C# / .NET / WinForms / Desktop Apps / Software Entwicklung nicht" hast Du weiter oben ja schon passiv erhalten, wie man das eigentlich umsetzen würde.
Gemacht hast das ja nicht, ist ja weiterhin statisch orientierter Spaghetti Code. Wenn Du das so behalten willst; tjo, dann ist das eben so, wird auch irgendwie schon funktionieren, aber dann bleibt halt auch der Code auf dem Level.
Weiß also nicht, was Du für eine Antwort Dir wünscht, wenn das eigentlich ja weiter oben schon steht 🙂

Es wird auch farblich markiert, aber der else Zweig für dir rote Farbe wird nie
ausgeführt. Weshalb?

Wir haben leider auch keine Glaskugel, aber deswegen gibts den Debugger.
[Artikel] Debugger: Wie verwende ich den von Visual Studio?

T
tristar Themenstarter:in
98 Beiträge seit 2016
vor einem Jahr

Verstanden hab ich es ... hab aber eine schnelle Umsetzung gebraucht.
ABER ich arbeite mich jetzt in Repository Pattern ein.