internal void MergeRows(DataRow[] rows)
{
DataTable src = null;
DataTable dst = null;
DataKey key = default(DataKey);
Index ndxSearch = null;
bool fEnforce = _dataSet.EnforceConstraints;
_dataSet.EnforceConstraints = false;
for (int i = 0; i < rows.Length; i++)
{
DataRow row = rows[i];
if (row == null)
{
throw ExceptionBuilder.ArgumentNull($"{nameof(rows)}[{i}]");
}
if (row.Table == null)
{
throw ExceptionBuilder.ArgumentNull($"{nameof(rows)}[{i}].{nameof(DataRow.Table)}");
}
//somebody is doing an 'automerge'
if (row.Table.DataSet == _dataSet)
{
continue;
}
if (src != row.Table)
{ // row.Table changed from prev. row.
src = row.Table;
dst = MergeSchema(row.Table);
if (dst == null)
{
Debug.Assert(MissingSchemaAction.Ignore == _missingSchemaAction, "MergeSchema failed");
_dataSet.EnforceConstraints = fEnforce;
return;
}
if (dst._primaryKey != null)
{
key = GetSrcKey(src, dst);
}
if (key.HasValue)
{
// Getting our own copy instead. ndxSearch = dst.primaryKey.Key.GetSortIndex();
// IMO, Better would be to reuse index
// ndxSearch = dst.primaryKey.Key.GetSortIndex(DataViewRowState.OriginalRows | DataViewRowState.Added );
if (null != ndxSearch)
{
ndxSearch.RemoveRef();
ndxSearch = null;
}
ndxSearch = new Index(dst, dst._primaryKey.Key.GetIndexDesc(), DataViewRowState.OriginalRows | DataViewRowState.Added, null);
ndxSearch.AddRef(); // need to addref twice, otherwise it will be collected
ndxSearch.AddRef(); // in past first adref was done in const
}
}
if (row._newRecord == -1 && row._oldRecord == -1)
{
continue;
}
DataRow targetRow = null;
if (0 < dst.Rows.Count && ndxSearch != null)
{
targetRow = dst.FindMergeTarget(row, key, ndxSearch);
}
targetRow = dst.MergeRow(row, targetRow, _preserveChanges, ndxSearch);
if (targetRow.Table._dependentColumns != null && targetRow.Table._dependentColumns.Count > 0)
{
targetRow.Table.EvaluateExpressions(targetRow, DataRowAction.Change, null);
}
}
if (null != ndxSearch)
{
ndxSearch.RemoveRef();
ndxSearch = null;
}
_dataSet.EnforceConstraints = fEnforce;
}
/// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public void Merge(DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction) { IntPtr hscp; Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, preserveChanges=%d{bool}, missingSchemaAction=%d{ds.MissingSchemaAction}\n", ObjectID, preserveChanges, (int)missingSchemaAction); try { // Argument checks if (rows == null) throw ExceptionBuilder.ArgumentNull("rows"); switch (missingSchemaAction) { // @perfnote: Enum.IsDefined case MissingSchemaAction.Add: case MissingSchemaAction.Ignore: case MissingSchemaAction.Error: case MissingSchemaAction.AddWithKey: Merger merger = new Merger(this, preserveChanges, missingSchemaAction); merger.MergeRows(rows); break; default: throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction); } } finally { Bid.ScopeLeave(ref hscp); } }