在C#(.NET 3.5)中,我使用数据库中的行填充了DataTable。在这个DataTable中,大约有100到200个DataRows。我必须遍历此DataTable以检查数据是否正确并且我使用了27种检查方法。首先,我试图将DataTable传递给每个方法并循环它。在我的第二次尝试中,我循环了DataTable一次并将DataRow传递给每个方法。之后我对这两种方法进行了基准测试,第一种方法比第二种方法更快?
将DataTable循环27次需要13秒。
循环使用DataTable 1次需要18秒。
那么对此有何解释?什么是循环使用DataTable检查数据的最快方法?
注意:基准测试是在我开始检查方法之前启动的,以排除与数据库的连接速度。
第一种方法:
private void check()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
checkStamnr();
checkVoornaam();
checkGebDatum();
...
sw.Stop();
sw.Reset();
}
private void checkStamnr()
{
foreach (DataRow dr in dtIdentificatieRecords.Rows)
{
if (dr["STAMNRVOL"] == null || dr["STAMNRVOL"].GetType() == typeof(DBNull) || dr["STAMNRVOL"].equals(""))
{
DatabankFout df = new DatabankFout("Stamnummer is leeg.");
listDBFouten.Add(df);
}
}
}
第二种方法
private void check()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
foreach (DataRow dr in dtIdentificatieRecords.Rows)
{
checkStamnr(dr);
checkVoornaam(dr);
checkGebDatum(dr);
...
}
sw.Stop();
sw.Reset();
}
private void checkStamnr(DataRow dr)
{
if (dr["STAMNRVOL"] == null || dr["STAMNRVOL"].GetType() == typeof(DBNull) || dr["STAMNRVOL"].equals(""))
{
DatabankFout df = new DatabankFout("Stamnummer is leeg.");
listDBFouten.Add(df);
}
}
根据要求Class DatabankFout:
public class DatabankFout
{
public DatabankFout(string reden, bool rood)
{
this.reden = reden;
this.rood = rood;
}
public DatabankFout(string reden) : this(reden, false)
{
}
public string reden { get; set; }
public bool rood { get; set; }
}
答案 0 :(得分:1)
我想说,一次运行中只有25%的运行时间差异并不重要。 对列表中的10000个项目至少运行10次测试。 如果第一个仍然更快,我将有一些想法。
主要部分时间可能来自创建DatabankFout,它可能是数据库连接。
答案 1 :(得分:1)
对我来说似乎不可能。我在我的机器上进行了测试。你的第一个多循环方法比一个循环方法运行得慢得多。
请查看我附带的控制台演示。
class Program
{
DataTable dtIdentificatieRecords = GetTable();
String checkTimeSpan, check2TimeSpan;
static void Main(string[] args)
{
Program Test = new Program();
Test.check();
Test.check2();
Console.WriteLine("checkTimeSpan: {0}", Test.checkTimeSpan);
Console.WriteLine("check2TimeSpan: {0}", Test.check2TimeSpan);
Console.ReadLine();
}
/// <summary>
/// This example method generates a DataTable.
/// </summary>
static DataTable GetTable()
{
//
// Here we create a DataTable with four columns.
//
DataTable table = new DataTable();
table.Columns.Add("STAMNRVOL", typeof(string));
table.Columns.Add("Drug", typeof(string));
table.Columns.Add("Patient", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
//
// Here we add five DataRows.
//
for (int a = 0; a < 999999; a++)
{
table.Rows.Add(a%2==0?a.ToString():"", "Indocin", "David", DateTime.Now);
}
return table;
}
private void check()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
checkStamnr();
checkStamnr();
checkStamnr();
checkStamnr();
checkStamnr();
stopwatch.Stop();
checkTimeSpan = stopwatch.Elapsed.TotalSeconds.ToString();
stopwatch.Reset();
}
private void checkStamnr()
{
foreach (DataRow dr in dtIdentificatieRecords.Rows)
{
if (dr["STAMNRVOL"] == null || dr["STAMNRVOL"].GetType() == typeof(DBNull) || dr["STAMNRVOL"].Equals(""))
{
DatabankFout df = new DatabankFout("Stamnummer is leeg.");
}
}
}
private void check2()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
foreach (DataRow dr2 in dtIdentificatieRecords.Rows)
{
checkStamnr2(dr2);
checkStamnr2(dr2);
checkStamnr2(dr2);
checkStamnr2(dr2);
checkStamnr2(dr2);
}
sw.Stop();
check2TimeSpan = sw.Elapsed.TotalSeconds.ToString();
sw.Reset();
}
private void checkStamnr2(DataRow dr)
{
if (dr["STAMNRVOL"] == null || dr["STAMNRVOL"].GetType() == typeof(DBNull) || dr["STAMNRVOL"].Equals(""))
{
DatabankFout df = new DatabankFout("Stamnummer is leeg.");
}
}
}
public class DatabankFout
{
public DatabankFout(string reden, bool rood)
{
this.reden = reden;
this.rood = rood;
}
public DatabankFout(string reden)
: this(reden, false)
{
}
public string reden { get; set; }
public bool rood { get; set; }
}