2012-02-07 253 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; } 
}