Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Performance verbessern
tristar
myCSharp.de - Member



Dabei seit:
Beiträge: 72

Themenstarter:

Performance verbessern

beantworten | zitieren | melden

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; ;
            }
        }
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.928

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
tristar
myCSharp.de - Member



Dabei seit:
Beiträge: 72

Themenstarter:

beantworten | zitieren | melden

@Abt danke für deine Hilfe!
Ich werde mich mal an die Überarbeitung machen ...
Zitat
- 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?!
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.928

beantworten | zitieren | melden

- 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
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 2.002
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
M.L.
myCSharp.de - Member



Dabei seit:
Beiträge: 301

beantworten | zitieren | melden

..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 ;-)
private Nachricht | Beiträge des Benutzers
tristar
myCSharp.de - Member



Dabei seit:
Beiträge: 72

Themenstarter:

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.928

beantworten | zitieren | melden

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 :-)
Zitat
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?
private Nachricht | Beiträge des Benutzers
tristar
myCSharp.de - Member



Dabei seit:
Beiträge: 72

Themenstarter:

beantworten | zitieren | melden

Verstanden hab ich es ... hab aber eine schnelle Umsetzung gebraucht.
ABER ich arbeite mich jetzt in Repository Pattern ein.
private Nachricht | Beiträge des Benutzers