2012-04-28 2 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.list имеет тип DataRowCollection.DataRowTree, полученный из RBTree<DataRow>.

private sealed class DataRowTree : RBTree<DataRow> 

RBTree<DataRow> и RBTreeNodeId позволяет сделать вывод о том, что a Red-Black tree используется!

+0

Я просто посмотрел на красно-черное дерево, и кажется, что этот метод способен динамически управлять массивами, не имея необходимости каждый раз строить всю структуру с нуля. Очень умно. Я чувствую, что могу доверять тому, что Add() - это быстрый эффективный способ работы с строками таблицы. И я посмотрю на DotPeek. Спасибо за ваш вклад. Очень полезно. – jwrightmail

Смежные вопросы