private void UpdateRowExecute(RowUpdatedEventArgs rowUpdatedEvent, IDbCommand dataCommand, StatementType cmdIndex)
{
Debug.Assert(null != rowUpdatedEvent, "null rowUpdatedEvent");
Debug.Assert(null != dataCommand, "null dataCommand");
Debug.Assert(rowUpdatedEvent.Command == dataCommand, "dataCommand differs from rowUpdatedEvent");
bool insertAcceptChanges = true;
UpdateRowSource updatedRowSource = dataCommand.UpdatedRowSource;
if ((StatementType.Delete == cmdIndex) || (0 == (UpdateRowSource.FirstReturnedRecord & updatedRowSource)))
{
int recordsAffected = dataCommand.ExecuteNonQuery();
rowUpdatedEvent.AdapterInit(recordsAffected);
}
else if ((StatementType.Insert == cmdIndex) || (StatementType.Update == cmdIndex))
{
// we only care about the first row of the first result
using (IDataReader dataReader = dataCommand.ExecuteReader(CommandBehavior.SequentialAccess))
{
DataReaderContainer readerHandler = DataReaderContainer.Create(dataReader, ReturnProviderSpecificTypes);
try
{
bool getData = false;
do
{
// advance to the first row returning result set
// determined by actually having columns in the result set
if (0 < readerHandler.FieldCount)
{
getData = true;
break;
}
} while (dataReader.NextResult());
if (getData && (0 != dataReader.RecordsAffected))
{
SchemaMapping mapping = new SchemaMapping(this, null, rowUpdatedEvent.Row.Table, readerHandler, false, SchemaType.Mapped, rowUpdatedEvent.TableMapping.SourceTable, true, null, null);
if ((null != mapping.DataTable) && (null != mapping.DataValues))
{
if (dataReader.Read())
{
if ((StatementType.Insert == cmdIndex) && insertAcceptChanges)
{
rowUpdatedEvent.Row.AcceptChanges();
insertAcceptChanges = false;
}
mapping.ApplyToDataRow(rowUpdatedEvent.Row);
}
}
}
}
finally
{
// using Close which can optimize its { while(dataReader.NextResult()); } loop
dataReader.Close();
// RecordsAffected is available after Close, but don't trust it after Dispose
int recordsAffected = dataReader.RecordsAffected;
rowUpdatedEvent.AdapterInit(recordsAffected);
}
}
}
else
{
// StatementType.Select, StatementType.Batch
Debug.Assert(false, "unexpected StatementType");
}
// map the parameter results to the dataSet
if (((StatementType.Insert == cmdIndex) || (StatementType.Update == cmdIndex))
&& (0 != (UpdateRowSource.OutputParameters & updatedRowSource)) && (0 != rowUpdatedEvent.RecordsAffected))
{
if ((StatementType.Insert == cmdIndex) && insertAcceptChanges)
{
rowUpdatedEvent.Row.AcceptChanges();
}
ParameterOutput(dataCommand.Parameters, rowUpdatedEvent.Row, rowUpdatedEvent.TableMapping);
}
// Only error if RecordsAffect == 0, not -1. A value of -1 means no count was received from server,
// do not error in that situation (means 'set nocount on' was executed on server).
switch (rowUpdatedEvent.Status)
{
case UpdateStatus.Continue:
switch (cmdIndex)
{
case StatementType.Update:
case StatementType.Delete:
if (0 == rowUpdatedEvent.RecordsAffected)
{
Debug.Assert(null == rowUpdatedEvent.Errors, "Continue - but contains an exception");
rowUpdatedEvent.Errors = ADP.UpdateConcurrencyViolation(cmdIndex, rowUpdatedEvent.RecordsAffected, 1, new DataRow[] { rowUpdatedEvent.Row });
rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred;
}
break;
}
break;
}
}