2012-04-28 43 views
3

DataTable.Rows.Add()向數據表中添加一行。但是,它如何處理底層數組呢?Collection.Add的工作流()

當一次添加一行時,它是否重建每個行添加的整個數組?

或者它是否能夠簡單地修改現有陣列而不會對性能產生任何影響?

我想知道在填充數據之前確定數組大小還是更好,或者如果數據表能夠在沒有(幕後)複製和移動的情況下修改集合。

我的理解是,要調整數組,您必須重新定義它並將先前存在的數據移動到新結構中。

我的問題是什麼是Collection.Add()方法的工作流程?

回答

3

看看使用的軟件,如DotPeek

DataTable.Rows.Add(DataRow row) 
{ 
    this.table.AddRow(row, -1); 
} 

的呼叫:

DataTable.AddRow(DataRow row, int proposedID) 
{ 
    this.InsertRow(row, proposedID, -1); 
} 

的呼叫:

DataTable.InsertRow(DataRow row, int proposedID, int pos) 
{ 
    this.InsertRow(row, (long) proposedID, pos, true); 
} 

的呼叫:

DataTable.InsertRow(DataRow row, long proposedID, int pos, bool fireEvent) 
{ 
    Exception deferredException = (Exception) null; 
    if (row == null) 
     throw ExceptionBuilder.ArgumentNull("row"); 
    if (row.Table != this) 
     throw ExceptionBuilder.RowAlreadyInOtherCollection(); 
    if (row.rowID != -1L) 
     throw ExceptionBuilder.RowAlreadyInTheCollection(); 
    row.BeginEdit(); 
    int proposedRecord = row.tempRecord; 
    row.tempRecord = -1; 
    if (proposedID == -1L) 
     proposedID = this.nextRowID; 
    bool flag; 
    if (flag = this.nextRowID <= proposedID) 
     this.nextRowID = checked (proposedID + 1L); 
    try 
    { 
     try 
     { 
      row.rowID = proposedID; 
      this.SetNewRecordWorker(row, proposedRecord, DataRowAction.Add, false, false, pos, fireEvent, out deferredException); 
     } 
     catch 
     { 
      if (flag && this.nextRowID == proposedID + 1L) 
       this.nextRowID = proposedID; 
      row.rowID = -1L; 
      row.tempRecord = proposedRecord; 
      throw; 
     } 
     if (deferredException != null) 
      throw deferredException; 
     if (!this.EnforceConstraints || this.inLoad) 
      return; 
     int count = this.columnCollection.Count; 
     for (int index = 0; index < count; ++index) 
     { 
      DataColumn dataColumn = this.columnCollection[index]; 
      if (dataColumn.Computed) 
       dataColumn.CheckColumnConstraint(row, DataRowAction.Add); 
     } 
    } 
    finally 
    { 
     row.ResetLastChangedColumn(); 
    } 
} 

的呼叫:

DataTable.SetNewRecordWorker(DataRow row, int proposedRecord, DataRowAction action, bool isInMerge, bool suppressEnsurePropertyChanged, int position, bool fireEvent, out Exception deferredException) 
{ 
    deferredException = (Exception) null; 
    if (row.tempRecord != proposedRecord) 
    { 
    if (!this.inDataLoad) 
    { 
     row.CheckInTable(); 
     this.CheckNotModifying(row); 
    } 
    if (proposedRecord == row.newRecord) 
    { 
     if (!isInMerge) 
     return; 
     this.RaiseRowChanged((DataRowChangeEventArgs) null, row, action); 
     return; 
    } 
    else 
     row.tempRecord = proposedRecord; 
    } 
    DataRowChangeEventArgs args = (DataRowChangeEventArgs) null; 
    try 
    { 
    row._action = action; 
    args = this.RaiseRowChanging((DataRowChangeEventArgs) null, row, action, fireEvent); 
    } 
    catch 
    { 
    row.tempRecord = -1; 
    throw; 
    } 
    finally 
    { 
    row._action = DataRowAction.Nothing; 
    } 
    row.tempRecord = -1; 
    int record = row.newRecord; 
    int num = proposedRecord != -1 ? proposedRecord : (row.RowState != DataRowState.Unchanged ? row.oldRecord : -1); 
    if (action == DataRowAction.Add) 
    { 
    if (position == -1) 
     this.Rows.ArrayAdd(row); 
    else 
     this.Rows.ArrayInsert(row, position); 
    } 
    List<DataRow> cachedRows = (List<DataRow>) null; 
    if ((action == DataRowAction.Delete || action == DataRowAction.Change) && (this.dependentColumns != null && this.dependentColumns.Count > 0)) 
    { 
    cachedRows = new List<DataRow>(); 
    for (int index = 0; index < this.ParentRelations.Count; ++index) 
    { 
     DataRelation relation = this.ParentRelations[index]; 
     if (relation.ChildTable == row.Table) 
     cachedRows.InsertRange(cachedRows.Count, (IEnumerable<DataRow>) row.GetParentRows(relation)); 
    } 
    for (int index = 0; index < this.ChildRelations.Count; ++index) 
    { 
     DataRelation relation = this.ChildRelations[index]; 
     if (relation.ParentTable == row.Table) 
     cachedRows.InsertRange(cachedRows.Count, (IEnumerable<DataRow>) row.GetChildRows(relation)); 
    } 
    } 
    if (!suppressEnsurePropertyChanged && !row.HasPropertyChanged && (row.newRecord != proposedRecord && -1 != proposedRecord) && -1 != row.newRecord) 
    { 
    row.LastChangedColumn = (DataColumn) null; 
    row.LastChangedColumn = (DataColumn) null; 
    } 
    if (this.LiveIndexes.Count != 0) 
    { 
    if (-1 == record && -1 != proposedRecord && (-1 != row.oldRecord && proposedRecord != row.oldRecord)) 
     record = row.oldRecord; 
    DataViewRowState recordState1 = row.GetRecordState(record); 
    DataViewRowState recordState2 = row.GetRecordState(num); 
    row.newRecord = proposedRecord; 
    if (proposedRecord != -1) 
     this.recordManager[proposedRecord] = row; 
    DataViewRowState recordState3 = row.GetRecordState(record); 
    DataViewRowState recordState4 = row.GetRecordState(num); 
    this.RecordStateChanged(record, recordState1, recordState3, num, recordState2, recordState4); 
    } 
    else 
    { 
    row.newRecord = proposedRecord; 
    if (proposedRecord != -1) 
     this.recordManager[proposedRecord] = row; 
    } 
    row.ResetLastChangedColumn(); 
    if (-1 != record && record != row.oldRecord && (record != row.tempRecord && record != row.newRecord) && row == this.recordManager[record]) 
    this.FreeRecord(ref record); 
    if (row.RowState == DataRowState.Detached && row.rowID != -1L) 
    this.RemoveRow(row, false); 
    if (this.dependentColumns != null) 
    { 
    if (this.dependentColumns.Count > 0) 
    { 
     try 
     { 
     this.EvaluateExpressions(row, action, cachedRows); 
     } 
     catch (Exception ex) 
     { 
     if (action != DataRowAction.Add) 
      throw ex; 
     deferredException = ex; 
     } 
    } 
    } 
    try 
    { 
    if (!fireEvent) 
     return; 
    this.RaiseRowChanged(args, row, action); 
    } 
    catch (Exception ex) 
    { 
    if (!ADP.IsCatchableExceptionType(ex)) 
     throw; 
    else 
     ExceptionBuilder.TraceExceptionWithoutRethrow(ex); 
    } 
} 

它調用那些之一:

DataRowCollection.ArrayAdd(DataRow row) 
{ 
    row.RBTreeNodeId = this.list.Add(row); 
} 

DataRowCollection.ArrayInsert(DataRow row, int pos) 
{ 
    row.RBTreeNodeId = this.list.Insert(pos, row); 
} 

this.listDataRowCollection.DataRowTree類型,從RBTree<DataRow>衍生的。

private sealed class DataRowTree : RBTree<DataRow> 

RBTree<DataRow>RBTreeNodeId使我們能夠得出這樣的結論a Red-Black tree正在使用!

+0

我剛看了一個紅黑樹,看起來這種方法能夠動態地管理陣列,而無需每次都從頭開始構建整個結構。非常聰明。我覺得我可以相信Add()是處理Table Rows的快速有效方法。我會看看DotPeek。謝謝您的意見。很有幫助。 – jwrightmail 2012-05-03 16:51:20