2012-02-07 235 views
2

在C#(.NET 3.5)中,我用数据库中的行填充了一个DataTable。在这个DataTable中大约有100到200个DataRows。我必须遍历这个DataTable来检查数据是否正确,我使用了27个检查方法。首先,我试图将DataTable传递给每个方法并对其进行循环。在我的第二次尝试中,我循环了一次DataTable,并将DataRow传递给每个方法。之后,我对这两种方法进行了基准测试,第一种方法比第二种方法更快?多次循环遍历DataTable

使数据表循环27次需要13秒。

循环数据表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); 
    } 
} 

类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; } 
} 
+2

努力帮助没有seing任何代码... – 2012-02-07 08:25:24

+0

增加了一些代码;-) – Yoni 2012-02-07 08:32:46

+1

如何重是你的'DatabankFout'类的,什么是'listDBFouten'?要检查哪种方法更快,您应该删除两者中相同的所有不相关的。循环100行肯定不能持续13/18秒(除非你在C64上),也许你已经使用了StopWatch并且在调试时忘记停止/重置(13毫秒更真实)。您不应传递wohole数据表或数据行,而应该只传递所需的数据 - 存储在datacolumn中的数据。 – 2012-02-07 09:03:40

回答

1

我要说的是在一次运行中一个的25%运行时间差有这么少的项目并不重要。 对列表中的10000个项目运行测试至少10次。 如果第一个更快,我会有一些想法。

时间的主要部分可能来自创建DatabankFout,它可能是一个数据库连接。

+0

DatabankFout只有属性,并没有与数据库的任何连接。 – Yoni 2012-02-07 09:16:43

+0

那么如何才能这么久?我们正在谈论几千个房地产比较。这可以在1秒内完成。是否listDBFouten.Add类似排序或其他缓慢的东西? – 2012-02-07 09:24:03

+0

您可以在我的开场白中看到DatabankFout。我只是尝试循环使用DataTable 1000次而没有任何检查方法,并在7ms内完成。然后我用一种检查方法试了一下,一分钟后还没有完成。 – Yoni 2012-02-07 09:25:06

1

对我来说这似乎是不可能的。我在我的机器上运行了一个测试。你的第一个多重循环方法比一个循环更慢。

enter image description here

请检查控制台演示中,我连接。

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; } 
}