System.Data.DataTable.SetNewRecordWorker C# (CSharp) Method

SetNewRecordWorker() private method

private SetNewRecordWorker ( DataRow row, int proposedRecord, DataRowAction action, bool isInMerge, bool suppressEnsurePropertyChanged, int position, bool fireEvent, Exception &deferredException ) : void
row DataRow
proposedRecord int
action DataRowAction
isInMerge bool
suppressEnsurePropertyChanged bool
position int
fireEvent bool
deferredException Exception
return void
        private void SetNewRecordWorker(DataRow row, int proposedRecord, DataRowAction action, bool isInMerge, bool suppressEnsurePropertyChanged,
            int position, bool fireEvent, out Exception deferredException)
        {
            // this is the event workhorse... it will throw the changing/changed events
            // and update the indexes. Used by change, add, delete, revert.

            // order of execution is as follows
            //
            // 1) set temp record
            // 2) Check constraints for non-expression columns
            // 3) Raise RowChanging/RowDeleting with temp record
            // 4) set the new record in storage
            // 5) Update indexes with recordStateChanges - this will fire ListChanged & PropertyChanged events on associated views
            // 6) Evaluate all Expressions (exceptions are deferred)- this will fire ListChanged & PropertyChanged events on associated views
            // 7) Raise RowChanged/ RowDeleted
            // 8) Check constraints for expression columns

            Debug.Assert(row != null, "Row can't be null.");
            deferredException = null;

            if (row._tempRecord != proposedRecord)
            {
                // $HACK: for performance reasons, EndUpdate calls SetNewRecord with tempRecord == proposedRecord
                if (!_inDataLoad)
                {
                    row.CheckInTable();
                    CheckNotModifying(row);
                }
                if (proposedRecord == row._newRecord)
                {
                    if (isInMerge)
                    {
                        Debug.Assert(fireEvent, "SetNewRecord is called with wrong parameter");
                        RaiseRowChanged(null, row, action);
                    }
                    return;
                }

                Debug.Assert(!row._inChangingEvent, "How can this row be in an infinite loop?");

                row._tempRecord = proposedRecord;
            }
            DataRowChangeEventArgs drcevent = null;

            try
            {
                row._action = action;
                drcevent = RaiseRowChanging(null, row, action, fireEvent);
            }
            catch
            {
                row._tempRecord = -1;
                throw;
            }
            finally
            {
                row._action = DataRowAction.Nothing;
            }

            row._tempRecord = -1;

            int currentRecord = row._newRecord;

            // if we're deleting, then the oldRecord value will change, so need to track that if it's distinct from the newRecord.
            int secondRecord = (proposedRecord != -1 ?
                                proposedRecord :
                                (row.RowState != DataRowState.Unchanged ?
                                 row._oldRecord :
                                 -1));

            if (action == DataRowAction.Add)
            {
                //if we come here from insert we do insert the row to collection
                if (position == -1)
                {
                    Rows.ArrayAdd(row);
                }
                else
                {
                    Rows.ArrayInsert(row, position);
                }
            }

            List<DataRow> cachedRows = null;
            if ((action == DataRowAction.Delete || action == DataRowAction.Change) &&
                _dependentColumns != null && _dependentColumns.Count > 0)
            {
                // if there are expression columns, need to cache related rows for deletes and updates (key changes)
                // before indexes are modified.
                cachedRows = new List<DataRow>();
                for (int j = 0; j < ParentRelations.Count; j++)
                {
                    DataRelation relation = ParentRelations[j];
                    if (relation.ChildTable != row.Table)
                    {
                        continue;
                    }
                    cachedRows.InsertRange(cachedRows.Count, row.GetParentRows(relation));
                }

                for (int j = 0; j < ChildRelations.Count; j++)
                {
                    DataRelation relation = ChildRelations[j];
                    if (relation.ParentTable != row.Table)
                    {
                        continue;
                    }
                    cachedRows.InsertRange(cachedRows.Count, row.GetChildRows(relation));
                }
            }

            // if the newRecord is changing, the propertychanged event should be allowed to triggered for ListChangedType.Changed or .Moved
            // unless the specific condition is known that no data has changed, like DataRow.SetModified()
            if (!suppressEnsurePropertyChanged && !row.HasPropertyChanged && (row._newRecord != proposedRecord)
                && (-1 != proposedRecord)
                && (-1 != row._newRecord))
            {
                // DataRow will believe multiple edits occured and
                // DataView.ListChanged event w/ ListChangedType.ItemChanged will raise DataRowView.PropertyChanged event and
                // PropertyChangedEventArgs.PropertyName will now be empty string so
                // WPF will refresh the entire row
                row.LastChangedColumn = null;
                row.LastChangedColumn = null;
            }

            // Check whether we need to update indexes
            if (LiveIndexes.Count != 0)
            {
                if ((-1 == currentRecord) && (-1 != proposedRecord) && (-1 != row._oldRecord) && (proposedRecord != row._oldRecord))
                {
                    // the transition from DataRowState.Deleted -> DataRowState.Modified
                    // with same orginal record but new current record
                    // needs to raise an ItemChanged or ItemMoved instead of ItemAdded in the ListChanged event.
                    // for indexes/views listening for both DataViewRowState.Deleted | DataViewRowState.ModifiedCurrent
                    currentRecord = row._oldRecord;
                }

                DataViewRowState currentRecordStatePre = row.GetRecordState(currentRecord);
                DataViewRowState secondRecordStatePre = row.GetRecordState(secondRecord);

                row._newRecord = proposedRecord;
                if (proposedRecord != -1)
                    _recordManager[proposedRecord] = row;

                DataViewRowState currentRecordStatePost = row.GetRecordState(currentRecord);
                DataViewRowState secondRecordStatePost = row.GetRecordState(secondRecord);

                // may raise DataView.ListChanged event
                RecordStateChanged(currentRecord, currentRecordStatePre, currentRecordStatePost,
                    secondRecord, secondRecordStatePre, secondRecordStatePost);
            }
            else
            {
                row._newRecord = proposedRecord;
                if (proposedRecord != -1)
                    _recordManager[proposedRecord] = row;
            }

            // reset the last changed column here, after all
            // DataViews have raised their DataRowView.PropertyChanged event
            row.ResetLastChangedColumn();

            // free the 'currentRecord' only after all the indexes have been updated.
            // Corruption! { if (currentRecord != row.oldRecord) { FreeRecord(ref currentRecord); } }
            // RecordStateChanged raises ListChanged event at which time user may do work
            if (-1 != currentRecord)
            {
                if (currentRecord != row._oldRecord)
                {
                    if ((currentRecord != row._tempRecord) &&   // Delete, AcceptChanges, BeginEdit
                        (currentRecord != row._newRecord) &&    // RejectChanges & SetAdded
                        (row == _recordManager[currentRecord])) // AcceptChanges, NewRow
                    {
                        FreeRecord(ref currentRecord);
                    }
                }
            }

            if (row.RowState == DataRowState.Detached && row.rowID != -1)
            {
                RemoveRow(row, false);
            }

            if (_dependentColumns != null && _dependentColumns.Count > 0)
            {
                try
                {
                    EvaluateExpressions(row, action, cachedRows);
                }
                catch (Exception exc)
                {
                    // For DataRows being added, throwing of exception from expression evaluation is
                    // deferred until after the row has been completely added.
                    if (action != DataRowAction.Add)
                    {
                        throw exc;
                    }
                    else
                    {
                        deferredException = exc;
                    }
                }
            }

            try
            {
                if (fireEvent)
                {
                    RaiseRowChanged(drcevent, row, action);
                }
            }
            catch (Exception e) when (ADP.IsCatchableExceptionType(e))
            {
                ExceptionBuilder.TraceExceptionWithoutRethrow(e); // ignore the exception
            }
        }
DataTable