Hallo zusammen,
um Daten zu validieren durchlaufe ich eine Tabelle spaltenweise in einer for-Schleife.
Zu jeder Spalte sind feste Regeln (manche optional) definiert:
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;
}
}
}
Also rein an der Schachtelei seh ich kaum eine Zeile, die man nicht in Richtung Peformance verbessern könnte 😃
Das ganze scheint übrigens auch nicht wirklich testbar zu sein, was ein Validator immer sein sollte.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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.