复制ado.net数据表列表的最快方式
本文关键字:方式 列表 ado net 数据表 复制 | 更新日期: 2023-09-27 18:18:53
我有一个列表的数据表,如
List<DataTable> a = new List<DataTable>();
我想对这个列表进行深度复制(即复制每个DataTable)。我的代码现在看起来像
List<DataTable> aCopy = new List<DataTable>();
for(int i = 0; i < a.Rows.Count; i++) {
aCopy.Add(a[i].Copy());
}
性能绝对是可怕的,我想知道是否有已知的方法来加快这样的副本?
编辑:不要担心为什么我有这个或需要这样做,只是接受它是遗留代码库的一部分,我不能改变
如果你必须复制一个数据表,它本质上是一个N时间的操作。如果数据表非常大,并且导致大量的分配,您可能能够通过一次执行一个部分来加快操作,但您实际上受到工作集的限制。
您可以尝试以下操作-它给了我性能提升,尽管您的里程可能会有所不同!我将其应用到您的示例中,以演示如何使用另一种机制复制数据表——克隆表,然后将数据流传入。您可以轻松地将其放入扩展方法中。
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。使用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]));
}
}
}
手术要花很长时间是不足为奇的;它不仅逐行执行,而且还执行额外的验证。
您应该指定列表的容量,否则它将不得不在内部增长以容纳数据。详细说明请参阅此处。
List<DataTable> aCopy = new List<DataTable>(a.Count);
我发现以下方法比其他过滤记录的方法(如LINQ)更有效,前提是您的搜索条件很简单:
public static DataTable FilterByEntityID(this DataTable table, int EntityID)
{
table.DefaultView.RowFilter = "EntityId = " + EntityID.ToString();
return table.DefaultView.ToTable();
}