Laden...

Performance Optimierung Datenvalidierung

Erstellt von Sythus vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.530 Views
S
Sythus Themenstarter:in
166 Beiträge seit 2009
vor 9 Jahren
Performance Optimierung Datenvalidierung

Hallo zusammen,

um Daten zu validieren durchlaufe ich eine Tabelle spaltenweise in einer for-Schleife.

Zu jeder Spalte sind feste Regeln (manche optional) definiert:

  • Datentyp
  • MaxLength
  • Whitelist (Daten die in der Spalte stehen dürfen)

Wie schon gesagt, durchlaufe ich die Spaltenwerte in einer for-schleife, prüfe in if Bedinungen die Regeln und teste anschließend auf DatenTyp, Maxlength usw.

Meine Frage ist nun: Gibt es dafür einen besseren Weg? Lässt sich beispielsweise eine ganze Liste aus String Werten performant auf Integer Werte prüfen?

Ich bin für jeden PerformanceTip dankbar.

Anbei auch der Code.


// Spaltenweise
            for (int i = 0; i < rules.Count; i++)
            {
                ValidationRules rule = rules[i];

                ExcelValidatorLog log = new ExcelValidatorLog("Errors of column: " + rule.headerName + Environment.NewLine);

                int excelColIndex = i + 1;

                for (int j = 2; j < excelData.GetLength(0); j++)
                {

                    string value = excelData[j, excelColIndex] == null ? null : excelData[j, excelColIndex].ToString();

                     if (string.IsNullOrEmpty(value) && rule.nullable == 0)
                    {
                        // Wert darf nicht null sein
                        log.Add(j, value, "Value is not allowed to be null or empty.");
                    }

                    switch (rule.dataType)
                    {
                        case 0:
                            // int
                            if (rule.nullable == 1 && value == null)
                                break;

                            int outInt = -1;
                            if (!int.TryParse(value, out outInt))
                            {
                                log.Add(j, value, "Value must be number.");
                            }
                            break;
                        case 1:
                            if (rule.nullable == 1 && value == null)
                                break;

                            // String - Größe prüfen
                            if (value.Length > rule.length)
                            {
                                log.Add(j, value, "Value length restriction of " + rule.length + " exceeded.");
                            }

                            // whitelist test
                            if (!string.IsNullOrEmpty(rule.whitelist))
                            {
                                string[] whiteListValues = rule.whitelist.Split(';');

                                if (!whiteListValues.Contains(value))
                                {
                                    log.Add(j, value, "Value must match a whitelist value.");
                                }
                            }
                            break;
                        case 2:
                            // Iso Länder Code
                            if (!isoCodeList.Contains(value))
                            {
                                log.Add(j, value, "Value is no isocode.");
                            }
                            break;
                        case 3:
                            // Datetime
                            if (string.IsNullOrEmpty(value) && rule.nullable == 1)
                                break; // its fine

                            try
                            {
                                double d = double.Parse(value);
                                DateTime conv = DateTime.FromOADate(d);
                            }
                            catch
                            {
                                log.Add(j, value, "Value must be a Datetime.");
                            }
                            break;
                        case 4:
                            float f = 1.0f;
                            if (!float.TryParse(value, out f))
                            {
                                log.Add(j, value, "Value must be a float value.");
                            }
                            break;
                        case 5:
                            // int
                            if (rule.nullable == 1 && value == null)
                                break; 

                            long outLong = -1;
                            if (!long.TryParse(value, out outLong))
                            {
                                log.Add(j, value, "Value must be number.");
                            }
                            break;
                        case 6:
                            // Datetime
                            if (string.IsNullOrEmpty(value) && rule.nullable == 1)
                                break; // its fine

                            try
                            {
                                double d = double.Parse(value);
                                DateTime conv = DateTime.FromOADate(d);
                                if (conv > DateTime.Now)
                                {
                                    // Wert darf nicht in der Zukunft liegen
                                    log.Add(j, value, "Date has to be in the past, but it is in the future.");
                                }
                            }
                            catch
                            {
                                log.Add(j, value, "Value must be a Datetime.");
                            }
                            break;
                    }
                    
                    if (rule.primaryKey.Value && excelColIndex == 1)
                    {
                        primaryKeys.Add(value);
                    }
                    else if(rule.primaryKey.Value)
                    {
                        primaryKeys[j-2] += value;
                    }
                }

            }

16.841 Beiträge seit 2008
vor 9 Jahren

Also rein an der Schachtelei seh ich kaum eine Zeile, die man nicht in Richtung Peformance verbessern könnte 😃

  • Asynchrones Log vermeided Add()-Overhead
  • Schleifen kann man hier wohl super auch via TPL umsetzen
  • List.Contains ist teurer als Array.Contains; oft ist sogar ein for mit if-überprüfung schneller aber nicht schöner
  • TryParse gehört ebenfalls nicht wirklich zu den Performance-Garanten; aber ist halt von Haus aus da und "schön".

Das ganze scheint übrigens auch nicht wirklich testbar zu sein, was ein Validator immer sein sollte.

W
872 Beiträge seit 2005
vor 9 Jahren

Wie holst Du erstmal die Daten aus Excel heraus? Wenn Du COM benutzt, ist es gut möglich, daß das einen großen Teil der Ausführungszeit kostet.
Vor allem solltest Du Deinen Code in kleine Funktionen aufspalten, die Du sowohl einzeln testen als auch von der Geschwindigkeit her messen kannst. Dann kannst Du priorisieren, welche Funktion, wie wichtig ist und die dann verbessern.