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; } }
private void UpdateRowExecute(RowUpdatedEventArgs rowUpdatedEvent, IDbCommand dataCommand, StatementType cmdIndex) { bool flag = true; UpdateRowSource updatedRowSource = dataCommand.UpdatedRowSource; if ((StatementType.Delete == cmdIndex) || ((UpdateRowSource.FirstReturnedRecord & updatedRowSource) == UpdateRowSource.None)) { int recordsAffected = dataCommand.ExecuteNonQuery(); rowUpdatedEvent.AdapterInit(recordsAffected); } else if ((StatementType.Insert == cmdIndex) || (StatementType.Update == cmdIndex)) { using (IDataReader reader = dataCommand.ExecuteReader(CommandBehavior.SequentialAccess)) { DataReaderContainer dataReader = DataReaderContainer.Create(reader, this.ReturnProviderSpecificTypes); try { bool flag2 = false; do { if (0 < dataReader.FieldCount) { flag2 = true; break; } } while (reader.NextResult()); if (flag2 && (reader.RecordsAffected != 0)) { SchemaMapping mapping = new SchemaMapping(this, null, rowUpdatedEvent.Row.Table, dataReader, false, SchemaType.Mapped, rowUpdatedEvent.TableMapping.SourceTable, true, null, null); if (((mapping.DataTable != null) && (mapping.DataValues != null)) && reader.Read()) { if ((StatementType.Insert == cmdIndex) && flag) { rowUpdatedEvent.Row.AcceptChanges(); flag = false; } mapping.ApplyToDataRow(rowUpdatedEvent.Row); } } } finally { reader.Close(); int num = reader.RecordsAffected; rowUpdatedEvent.AdapterInit(num); } } } if (((StatementType.Insert == cmdIndex) || (StatementType.Update == cmdIndex)) && (((UpdateRowSource.OutputParameters & updatedRowSource) != UpdateRowSource.None) && (rowUpdatedEvent.RecordsAffected != 0))) { if ((StatementType.Insert == cmdIndex) && flag) { rowUpdatedEvent.Row.AcceptChanges(); } this.ParameterOutput(dataCommand.Parameters, rowUpdatedEvent.Row, rowUpdatedEvent.TableMapping); } if (rowUpdatedEvent.Status == UpdateStatus.Continue) { switch (cmdIndex) { case StatementType.Update: case StatementType.Delete: if (rowUpdatedEvent.RecordsAffected == 0) { rowUpdatedEvent.Errors = ADP.UpdateConcurrencyViolation(cmdIndex, rowUpdatedEvent.RecordsAffected, 1, new DataRow[] { rowUpdatedEvent.Row }); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } return; } } }
private void UpdateBatchExecute(BatchCommandInfo[] batchCommands, int commandCount, RowUpdatedEventArgs rowUpdatedEvent) { try { // the batch execution may succeed, partially succeed and throw an exception (or not), or totally fail int recordsAffected = ExecuteBatch(); rowUpdatedEvent.AdapterInit(recordsAffected); } catch (DbException e) { // an exception was thrown be but some part of the batch may have been succesfull ADP.TraceExceptionForCapture(e); rowUpdatedEvent.Errors = e; rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } Data.MissingMappingAction missingMapping = UpdateMappingAction; Data.MissingSchemaAction missingSchema = UpdateSchemaAction; int checkRecordsAffected = 0; bool hasConcurrencyViolation = false; List<DataRow> rows = null; // walk through the batch to build the sum of recordsAffected // determine possible indivdual messages per datarow // determine possible concurrency violations per datarow // map output parameters to the datarow for (int bc = 0; bc < commandCount; ++bc) { BatchCommandInfo batchCommand = batchCommands[bc]; StatementType statementType = batchCommand._statementType; // default implementation always returns 1, derived classes must override // otherwise DbConcurrencyException will only be thrown if sum of all records in batch is 0 int rowAffected; if (GetBatchedRecordsAffected(batchCommand._commandIdentifier, out rowAffected, out batchCommands[bc]._errors)) { batchCommands[bc]._recordsAffected = rowAffected; } if ((null == batchCommands[bc]._errors) && batchCommands[bc]._recordsAffected.HasValue) { // determine possible concurrency violations per datarow if ((StatementType.Update == statementType) || (StatementType.Delete == statementType)) { checkRecordsAffected++; if (0 == rowAffected) { if (null == rows) { rows = new List<DataRow>(); } batchCommands[bc]._errors = ADP.UpdateConcurrencyViolation(batchCommands[bc]._statementType, 0, 1, new DataRow[] { rowUpdatedEvent.Rows[bc] }); hasConcurrencyViolation = true; rows.Add(rowUpdatedEvent.Rows[bc]); } } // map output parameters to the datarow if (((StatementType.Insert == statementType) || (StatementType.Update == statementType)) && (0 != (UpdateRowSource.OutputParameters & batchCommand._updatedRowSource)) && (0 != rowAffected)) { if (StatementType.Insert == statementType) { // AcceptChanges for 'added' rows so backend generated keys that are returned // propagte into the datatable correctly. rowUpdatedEvent.Rows[bc].AcceptChanges(); } for (int i = 0; i < batchCommand._parameterCount; ++i) { IDataParameter parameter = GetBatchedParameter(batchCommand._commandIdentifier, i); ParameterOutput(parameter, batchCommand._row, rowUpdatedEvent.TableMapping, missingMapping, missingSchema); } } } } if (null == rowUpdatedEvent.Errors) { // 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). if (UpdateStatus.Continue == rowUpdatedEvent.Status) { if ((0 < checkRecordsAffected) && ((0 == rowUpdatedEvent.RecordsAffected) || hasConcurrencyViolation)) { // bug50526, an exception if no records affected and attempted an Update/Delete Debug.Assert(null == rowUpdatedEvent.Errors, "Continue - but contains an exception"); DataRow[] rowsInError = (null != rows) ? rows.ToArray() : rowUpdatedEvent.Rows; rowUpdatedEvent.Errors = ADP.UpdateConcurrencyViolation(StatementType.Batch, commandCount - rowsInError.Length, commandCount, rowsInError); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } } } }
private void UpdateBatchExecute(BatchCommandInfo[] batchCommands, int commandCount, RowUpdatedEventArgs rowUpdatedEvent) { try { int recordsAffected = this.ExecuteBatch(); rowUpdatedEvent.AdapterInit(recordsAffected); } catch (DbException exception) { ADP.TraceExceptionForCapture(exception); rowUpdatedEvent.Errors = exception; rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } MissingMappingAction updateMappingAction = this.UpdateMappingAction; MissingSchemaAction updateSchemaAction = this.UpdateSchemaAction; int num4 = 0; bool flag = false; List<DataRow> list = null; for (int i = 0; i < commandCount; i++) { int num3; BatchCommandInfo info = batchCommands[i]; StatementType statementType = info.StatementType; if (this.GetBatchedRecordsAffected(info.CommandIdentifier, out num3, out batchCommands[i].Errors)) { batchCommands[i].RecordsAffected = new int?(num3); } if ((batchCommands[i].Errors == null) && batchCommands[i].RecordsAffected.HasValue) { if ((StatementType.Update == statementType) || (StatementType.Delete == statementType)) { num4++; if (num3 == 0) { if (list == null) { list = new List<DataRow>(); } batchCommands[i].Errors = ADP.UpdateConcurrencyViolation(batchCommands[i].StatementType, 0, 1, new DataRow[] { rowUpdatedEvent.Rows[i] }); flag = true; list.Add(rowUpdatedEvent.Rows[i]); } } if (((StatementType.Insert == statementType) || (StatementType.Update == statementType)) && (((UpdateRowSource.OutputParameters & info.UpdatedRowSource) != UpdateRowSource.None) && (num3 != 0))) { if (StatementType.Insert == statementType) { rowUpdatedEvent.Rows[i].AcceptChanges(); } for (int j = 0; j < info.ParameterCount; j++) { IDataParameter batchedParameter = this.GetBatchedParameter(info.CommandIdentifier, j); this.ParameterOutput(batchedParameter, info.Row, rowUpdatedEvent.TableMapping, updateMappingAction, updateSchemaAction); } } } } if ((((rowUpdatedEvent.Errors == null) && (rowUpdatedEvent.Status == UpdateStatus.Continue)) && (0 < num4)) && ((rowUpdatedEvent.RecordsAffected == 0) || flag)) { DataRow[] dataRows = (list != null) ? list.ToArray() : rowUpdatedEvent.Rows; rowUpdatedEvent.Errors = ADP.UpdateConcurrencyViolation(StatementType.Batch, commandCount - dataRows.Length, commandCount, dataRows); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } }