private void SetDataRowWithLoadOption(DataRow dataRow, int recordNo, LoadOption loadOption, bool checkReadOnly)
{
bool hasError = false;
if (checkReadOnly)
{
foreach (DataColumn dc in Columns)
{
if (dc.ReadOnly && !dc.Computed)
{
switch (loadOption)
{
case LoadOption.OverwriteChanges:
if ((dataRow[dc, DataRowVersion.Current] != dc[recordNo]) || (dataRow[dc, DataRowVersion.Original] != dc[recordNo]))
hasError = true;
break;
case LoadOption.Upsert:
if (dataRow[dc, DataRowVersion.Current] != dc[recordNo])
hasError = true;
break;
case LoadOption.PreserveChanges:
if (dataRow[dc, DataRowVersion.Original] != dc[recordNo])
hasError = true;
break;
}
}
}
} // No Event should be fired in SenNewRecord and SetOldRecord
// fire rowChanging event here
DataRowChangeEventArgs drcevent = null;
DataRowAction action = DataRowAction.Nothing;
int cacheTempRecord = dataRow._tempRecord;
dataRow._tempRecord = recordNo;
switch (loadOption)
{
case LoadOption.OverwriteChanges:
action = DataRowAction.ChangeCurrentAndOriginal;
break;
case LoadOption.Upsert:
switch (dataRow.RowState)
{
case DataRowState.Unchanged:
// let see if the incomming value has the same values as existing row, so compare records
foreach (DataColumn dc in dataRow.Table.Columns)
{
if (0 != dc.Compare(dataRow._newRecord, recordNo))
{
action = DataRowAction.Change;
break;
}
}
break;
case DataRowState.Deleted:
Debug.Assert(false, "LoadOption.Upsert with deleted row, should not be here");
break;
default:
action = DataRowAction.Change;
break;
}
break;
case LoadOption.PreserveChanges:
switch (dataRow.RowState)
{
case DataRowState.Unchanged:
action = DataRowAction.ChangeCurrentAndOriginal;
break;
default:
action = DataRowAction.ChangeOriginal;
break;
}
break;
default:
throw ExceptionBuilder.ArgumentOutOfRange(nameof(LoadOption));
}
try
{
drcevent = RaiseRowChanging(null, dataRow, action);
if (action == DataRowAction.Nothing)
{ // RaiseRowChanging does not fire for DataRowAction.Nothing
dataRow._inChangingEvent = true;
try
{
drcevent = OnRowChanging(drcevent, dataRow, action);
}
finally
{
dataRow._inChangingEvent = false;
}
}
}
finally
{
Debug.Assert(dataRow._tempRecord == recordNo, "tempRecord has been changed in event handler");
if (DataRowState.Detached == dataRow.RowState)
{
// 'row.Table.Remove(row);'
if (-1 != cacheTempRecord)
{
FreeRecord(ref cacheTempRecord);
}
}
else
{
if (dataRow._tempRecord != recordNo)
{
// 'row.EndEdit(); row.BeginEdit(); '
if (-1 != cacheTempRecord)
{
FreeRecord(ref cacheTempRecord);
}
if (-1 != recordNo)
{
FreeRecord(ref recordNo);
}
recordNo = dataRow._tempRecord;
}
else
{
dataRow._tempRecord = cacheTempRecord;
}
}
}
if (dataRow._tempRecord != -1)
{
dataRow.CancelEdit();
}
switch (loadOption)
{
case LoadOption.OverwriteChanges:
SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
SetOldRecord(dataRow, recordNo);
break;
case LoadOption.Upsert:
if (dataRow.RowState == DataRowState.Unchanged)
{
SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
if (!dataRow.HasChanges())
{
SetOldRecord(dataRow, recordNo);
}
}
else
{
if (dataRow.RowState == DataRowState.Deleted)
dataRow.RejectChanges();
SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
}
break;
case LoadOption.PreserveChanges:
if (dataRow.RowState == DataRowState.Unchanged)
{
// if ListChanged event deletes dataRow
SetOldRecord(dataRow, recordNo); // do not fire event
SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
}
else
{
// if modified/ added / deleted we want this operation to fire event (just for LoadOption.PreserveCurrentValues)
SetOldRecord(dataRow, recordNo);
}
break;
default:
throw ExceptionBuilder.ArgumentOutOfRange(nameof(LoadOption));
}
if (hasError)
{
string error = SR.Load_ReadOnlyDataModified;
if (dataRow.RowError.Length == 0)
{
dataRow.RowError = error;
}
else
{
dataRow.RowError += " ]:[ " + error;
}
foreach (DataColumn dc in Columns)
{
if (dc.ReadOnly && !dc.Computed)
{
dataRow.SetColumnError(dc, error);
}
}
}
drcevent = RaiseRowChanged(drcevent, dataRow, action);
if (action == DataRowAction.Nothing)
{
// RaiseRowChanged does not fire for DataRowAction.Nothing
dataRow._inChangingEvent = true;
try
{
OnRowChanged(drcevent, dataRow, action);
}
finally
{
dataRow._inChangingEvent = false;
}
}
}