2011-12-28 69 views
1

我有一個像最快的方式

List<DataTable> a = new List<DataTable>(); 

我想使這個列表的深層副本(即每一個複製數據表)數據表的列表。我的代碼目前看起來像

List<DataTable> aCopy = new List<DataTable>(); 
for(int i = 0; i < a.Rows.Count; i++) { 
    aCopy.Add(a[i].Copy()); 
} 

性能是絕對可怕的,我想知道是否有一種已知的方式來加快這樣的副本?

編輯:不要擔心,爲什麼我有這樣或需要這樣做,只是接受,這是一箇舊的代碼基礎的一部分,我不能改變

+0

如何「大」是數據表的名單? – 2011-12-28 16:25:42

+0

我不認爲你可以加快速度,同時仍然在處理這些要求。 (也就是說它是一個深層拷貝。)另外請注意,在你的代碼的RELEASE版本中,性能會比你的代碼的DEBUG版本更好。 – Dracorat 2011-12-28 16:30:00

回答

2

,如果你要複製的數據表它本質上是N次操作。如果數據表非常大並導致大量的分配,您可以通過每次執行一個部分來加快操作速度,但是您基本上受工作集限制。

2

你可以嘗試以下 - 它給了我一個性能提升,雖然你的里程可能會有所不同!我已經將它適用於您的示例,以演示如何使用備用機制來複制數據表 - 克隆表,然後流式傳輸數據。您可以輕鬆將其放入擴展方法中。

List<DataTable> aCopy = new List<DataTable>(); 
for(int i = 0; i < a.Rows.Count; i++) { 
    DataTable sourceTable = a[i]; 
    DataTable copyTable = sourceTable.Clone(); //Clones structure 
    copyTable.Load(sourceTable.CreateDataReader()); 
} 

這是許多倍以下的速度(約6在我的用例):

DataTable copyTable = sourceTable.Clone(); 
foreach(DataRow dr in sourceTable.Rows) 
{ 
    copyTable.ImportRow(dr); 
} 

而且,如果我們看一下DataTable.Copy使用ILSpy做:

public DataTable Copy() 
{ 
    IntPtr intPtr; 
    Bid.ScopeEnter(out intPtr, "<ds.DataTable.Copy|API> %d#\n", this.ObjectID); 
    DataTable result; 
    try 
    { 
     DataTable dataTable = this.Clone(); 
     foreach (DataRow row in this.Rows) 
     { 
      this.CopyRow(dataTable, row); 
     } 
     result = dataTable; 
    } 
    finally 
    { 
     Bid.ScopeLeave(ref intPtr); 
    } 
    return result; 
} 

internal void CopyRow(DataTable table, DataRow row) 
{ 
    int num = -1; 
    int newRecord = -1; 
    if (row == null) 
    { 
     return; 
    } 
    if (row.oldRecord != -1) 
    { 
     num = table.recordManager.ImportRecord(row.Table, row.oldRecord); 
    } 
    if (row.newRecord != -1) 
    { 
     if (row.newRecord != row.oldRecord) 
     { 
      newRecord = table.recordManager.ImportRecord(row.Table, row.newRecord); 
     } 
     else 
     { 
      newRecord = num; 
     } 
    } 
    DataRow dataRow = table.AddRecords(num, newRecord); 
    if (row.HasErrors) 
    { 
     dataRow.RowError = row.RowError; 
     DataColumn[] columnsInError = row.GetColumnsInError(); 
     for (int i = 0; i < columnsInError.Length; i++) 
     { 
      DataColumn column = dataRow.Table.Columns[columnsInError[i].ColumnName]; 
      dataRow.SetColumnError(column, row.GetColumnError(columnsInError[i])); 
     } 
    } 
} 

操作需要很長時間並不奇怪,它不僅是逐行的,而且還有額外的驗證。

0

您應該指定列表的容量,否則它將不得不在內部增長以適應數據。有關詳細說明,請參閱here

List<DataTable> aCopy = new List<DataTable>(a.Count); 
0

我發現下面的方法要比過濾的記錄,像LINQ其他方式更有效,只要你的搜索條件很簡單:

public static DataTable FilterByEntityID(this DataTable table, int EntityID) 
    { 
     table.DefaultView.RowFilter = "EntityId = " + EntityID.ToString(); 
     return table.DefaultView.ToTable(); 
    }