protected virtual int Update(DataRow[] dataRows, DataTableMapping tableMapping) { long logScopeId = DataCommonEventSource.Log.EnterScope("<comm.DbDataAdapter.Update|API> {0}, dataRows[], tableMapping", ObjectID); try { Debug.Assert((null != dataRows) && (0 < dataRows.Length), "Update: bad dataRows"); Debug.Assert(null != tableMapping, "Update: bad DataTableMapping"); // If records were affected, increment row count by one - that is number of rows affected in dataset. int cumulativeDataRowsAffected = 0; IDbConnection[] connections = new IDbConnection[5]; // one for each statementtype ConnectionState[] connectionStates = new ConnectionState[5]; // closed by default (== 0) bool useSelectConnectionState = false; IDbCommand tmpcmd = _IDbDataAdapter.SelectCommand; if (null != tmpcmd) { connections[0] = tmpcmd.Connection; if (null != connections[0]) { connectionStates[0] = connections[0].State; useSelectConnectionState = true; } } int maxBatchCommands = Math.Min(UpdateBatchSize, dataRows.Length); if (maxBatchCommands < 1) { // batch size of zero indicates one batch, no matter how large... maxBatchCommands = dataRows.Length; } BatchCommandInfo[] batchCommands = new BatchCommandInfo[maxBatchCommands]; DataRow[] rowBatch = new DataRow[maxBatchCommands]; int commandCount = 0; // the outer try/finally is for closing any connections we may have opened try { try { if (1 != maxBatchCommands) { InitializeBatching(); } StatementType statementType = StatementType.Select; IDbCommand dataCommand = null; // for each row which is either insert, update, or delete foreach (DataRow dataRow in dataRows) { if (null == dataRow) { continue; // foreach DataRow } bool isCommandFromRowUpdating = false; // obtain the appropriate command switch (dataRow.RowState) { case DataRowState.Detached: case DataRowState.Unchanged: continue; // foreach DataRow case DataRowState.Added: statementType = StatementType.Insert; dataCommand = _IDbDataAdapter.InsertCommand; break; case DataRowState.Deleted: statementType = StatementType.Delete; dataCommand = _IDbDataAdapter.DeleteCommand; break; case DataRowState.Modified: statementType = StatementType.Update; dataCommand = _IDbDataAdapter.UpdateCommand; break; default: Debug.Assert(false, "InvalidDataRowState"); throw ADP.InvalidDataRowState(dataRow.RowState); // out of Update without completing batch } // setup the event to be raised RowUpdatingEventArgs rowUpdatingEvent = CreateRowUpdatingEvent(dataRow, dataCommand, statementType, tableMapping); // this try/catch for any exceptions during the parameter initialization try { dataRow.RowError = null; if (null != dataCommand) { // prepare the parameters for the user who then can modify them during OnRowUpdating ParameterInput(dataCommand.Parameters, statementType, dataRow, tableMapping); } } catch (Exception e) when (ADP.IsCatchableExceptionType(e)) { ADP.TraceExceptionForCapture(e); rowUpdatingEvent.Errors = e; rowUpdatingEvent.Status = UpdateStatus.ErrorsOccurred; } OnRowUpdating(rowUpdatingEvent); // user may throw out of Update without completing batch IDbCommand tmpCommand = rowUpdatingEvent.Command; isCommandFromRowUpdating = (dataCommand != tmpCommand); dataCommand = tmpCommand; tmpCommand = null; // handle the status from RowUpdating event UpdateStatus rowUpdatingStatus = rowUpdatingEvent.Status; if (UpdateStatus.Continue != rowUpdatingStatus) { if (UpdateStatus.ErrorsOccurred == rowUpdatingStatus) { UpdatingRowStatusErrors(rowUpdatingEvent, dataRow); continue; // foreach DataRow } else if (UpdateStatus.SkipCurrentRow == rowUpdatingStatus) { if (DataRowState.Unchanged == dataRow.RowState) { cumulativeDataRowsAffected++; } continue; // foreach DataRow } else if (UpdateStatus.SkipAllRemainingRows == rowUpdatingStatus) { if (DataRowState.Unchanged == dataRow.RowState) { cumulativeDataRowsAffected++; } break; // execute existing batch and return } else { throw ADP.InvalidUpdateStatus(rowUpdatingStatus); // out of Update } } // else onward to Append/ExecuteNonQuery/ExecuteReader rowUpdatingEvent = null; RowUpdatedEventArgs rowUpdatedEvent = null; if (1 == maxBatchCommands) { if (null != dataCommand) { batchCommands[0]._commandIdentifier = 0; batchCommands[0]._parameterCount = dataCommand.Parameters.Count; batchCommands[0]._statementType = statementType; batchCommands[0]._updatedRowSource = dataCommand.UpdatedRowSource; } batchCommands[0]._row = dataRow; rowBatch[0] = dataRow; // not doing a batch update, just simplifying code... commandCount = 1; } else { Exception errors = null; try { if (null != dataCommand) { if (0 == (UpdateRowSource.FirstReturnedRecord & dataCommand.UpdatedRowSource)) { // append the command to the commandset. If an exception // occurs, then the user must append and continue batchCommands[commandCount]._commandIdentifier = AddToBatch(dataCommand); batchCommands[commandCount]._parameterCount = dataCommand.Parameters.Count; batchCommands[commandCount]._row = dataRow; batchCommands[commandCount]._statementType = statementType; batchCommands[commandCount]._updatedRowSource = dataCommand.UpdatedRowSource; rowBatch[commandCount] = dataRow; commandCount++; if (commandCount < maxBatchCommands) { continue; // foreach DataRow } // else onward execute the batch } else { // do not allow the expectation that returned results will be used errors = ADP.ResultsNotAllowedDuringBatch(); } } else { // null Command will force RowUpdatedEvent with ErrorsOccured without completing batch errors = ADP.UpdateRequiresCommand(statementType, isCommandFromRowUpdating); } } catch (Exception e) when (ADP.IsCatchableExceptionType(e)) { // try/catch for RowUpdatedEventArgs ADP.TraceExceptionForCapture(e); errors = e; } if (null != errors) { rowUpdatedEvent = CreateRowUpdatedEvent(dataRow, dataCommand, StatementType.Batch, tableMapping); rowUpdatedEvent.Errors = errors; rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; OnRowUpdated(rowUpdatedEvent); // user may throw out of Update if (errors != rowUpdatedEvent.Errors) { // user set the error msg and we will use it for (int i = 0; i < batchCommands.Length; ++i) { batchCommands[i]._errors = null; } } cumulativeDataRowsAffected += UpdatedRowStatus(rowUpdatedEvent, batchCommands, commandCount); if (UpdateStatus.SkipAllRemainingRows == rowUpdatedEvent.Status) { break; } continue; // foreach datarow } } rowUpdatedEvent = CreateRowUpdatedEvent(dataRow, dataCommand, statementType, tableMapping); // this try/catch for any exceptions during the execution, population, output parameters try { if (1 != maxBatchCommands) { IDbConnection connection = DbDataAdapter.GetConnection1(this); ConnectionState state = UpdateConnectionOpen(connection, StatementType.Batch, connections, connectionStates, useSelectConnectionState); rowUpdatedEvent.AdapterInit(rowBatch); if (ConnectionState.Open == state) { UpdateBatchExecute(batchCommands, commandCount, rowUpdatedEvent); } else { // null Connection will force RowUpdatedEvent with ErrorsOccured without completing batch rowUpdatedEvent.Errors = ADP.UpdateOpenConnectionRequired(StatementType.Batch, false, state); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } } else if (null != dataCommand) { IDbConnection connection = DbDataAdapter.GetConnection4(this, dataCommand, statementType, isCommandFromRowUpdating); ConnectionState state = UpdateConnectionOpen(connection, statementType, connections, connectionStates, useSelectConnectionState); if (ConnectionState.Open == state) { UpdateRowExecute(rowUpdatedEvent, dataCommand, statementType); batchCommands[0]._recordsAffected = rowUpdatedEvent.RecordsAffected; batchCommands[0]._errors = null; } else { // null Connection will force RowUpdatedEvent with ErrorsOccured without completing batch rowUpdatedEvent.Errors = ADP.UpdateOpenConnectionRequired(statementType, isCommandFromRowUpdating, state); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } } else { // null Command will force RowUpdatedEvent with ErrorsOccured without completing batch rowUpdatedEvent.Errors = ADP.UpdateRequiresCommand(statementType, isCommandFromRowUpdating); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } } catch (Exception e) when (ADP.IsCatchableExceptionType(e)) { // try/catch for RowUpdatedEventArgs ADP.TraceExceptionForCapture(e); rowUpdatedEvent.Errors = e; rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } bool clearBatchOnSkipAll = (UpdateStatus.ErrorsOccurred == rowUpdatedEvent.Status); { Exception errors = rowUpdatedEvent.Errors; OnRowUpdated(rowUpdatedEvent); // user may throw out of Update // NOTE: the contents of rowBatch are now tainted... if (errors != rowUpdatedEvent.Errors) { // user set the error msg and we will use it for (int i = 0; i < batchCommands.Length; ++i) { batchCommands[i]._errors = null; } } } cumulativeDataRowsAffected += UpdatedRowStatus(rowUpdatedEvent, batchCommands, commandCount); if (UpdateStatus.SkipAllRemainingRows == rowUpdatedEvent.Status) { if (clearBatchOnSkipAll && 1 != maxBatchCommands) { ClearBatch(); commandCount = 0; } break; // from update } if (1 != maxBatchCommands) { ClearBatch(); commandCount = 0; } for (int i = 0; i < batchCommands.Length; ++i) { batchCommands[i] = default(BatchCommandInfo); } commandCount = 0; } // foreach DataRow // must handle the last batch if (1 != maxBatchCommands && 0 < commandCount) { RowUpdatedEventArgs rowUpdatedEvent = CreateRowUpdatedEvent(null, dataCommand, statementType, tableMapping); try { IDbConnection connection = DbDataAdapter.GetConnection1(this); ConnectionState state = UpdateConnectionOpen(connection, StatementType.Batch, connections, connectionStates, useSelectConnectionState); DataRow[] finalRowBatch = rowBatch; if (commandCount < rowBatch.Length) { finalRowBatch = new DataRow[commandCount]; Array.Copy(rowBatch, 0, finalRowBatch, 0, commandCount); } rowUpdatedEvent.AdapterInit(finalRowBatch); if (ConnectionState.Open == state) { UpdateBatchExecute(batchCommands, commandCount, rowUpdatedEvent); } else { // null Connection will force RowUpdatedEvent with ErrorsOccured without completing batch rowUpdatedEvent.Errors = ADP.UpdateOpenConnectionRequired(StatementType.Batch, false, state); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } } catch (Exception e) when (ADP.IsCatchableExceptionType(e)) { // try/catch for RowUpdatedEventArgs ADP.TraceExceptionForCapture(e); rowUpdatedEvent.Errors = e; rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } Exception errors = rowUpdatedEvent.Errors; OnRowUpdated(rowUpdatedEvent); // user may throw out of Update // NOTE: the contents of rowBatch are now tainted... if (errors != rowUpdatedEvent.Errors) { // user set the error msg and we will use it for (int i = 0; i < batchCommands.Length; ++i) { batchCommands[i]._errors = null; } } cumulativeDataRowsAffected += UpdatedRowStatus(rowUpdatedEvent, batchCommands, commandCount); } } finally { if (1 != maxBatchCommands) { TerminateBatching(); } } } finally { // try/finally for connection cleanup for (int i = 0; i < connections.Length; ++i) { QuietClose(connections[i], connectionStates[i]); } } return cumulativeDataRowsAffected; } finally { DataCommonEventSource.Log.ExitScope(logScopeId); } }
private int UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, int commandCount) { Debug.Assert(null != batchCommands, "null batchCommands?"); Exception errors = rowUpdatedEvent.Errors; if (null == errors) { // user changed status to ErrorsOccured without supplying an exception message errors = ADP.RowUpdatedErrors(); rowUpdatedEvent.Errors = errors; } int affected = 0; bool done = false; string message = errors.Message; for (int i = 0; i < commandCount; i++) { DataRow row = batchCommands[i]._row; Debug.Assert(null != row, "null dataRow?"); if (null != batchCommands[i]._errors) { // will exist if 0 == RecordsAffected string rowMsg = batchCommands[i]._errors.Message; if (string.IsNullOrEmpty(rowMsg)) { rowMsg = message; } row.RowError += rowMsg; done = true; } } if (!done) { // all rows are in 'error' for (int i = 0; i < commandCount; i++) { DataRow row = batchCommands[i]._row; // its possible a DBConcurrencyException exists and all rows have records affected // via not overriding GetBatchedRecordsAffected or user setting the exception row.RowError += message; } } else { affected = UpdatedRowStatusContinue(rowUpdatedEvent, batchCommands, commandCount); } if (!ContinueUpdateOnError) { throw errors; // out of Update } return affected; // return the count of successful rows within the batch failure }
private int UpdatedRowStatusSkip(BatchCommandInfo[] batchCommands, int commandCount) { Debug.Assert(null != batchCommands, "null batchCommands?"); int cumulativeDataRowsAffected = 0; for (int i = 0; i < commandCount; i++) { DataRow row = batchCommands[i]._row; Debug.Assert(null != row, "null dataRow?"); if (0 != ((DataRowState.Detached | DataRowState.Unchanged) & row.RowState)) { cumulativeDataRowsAffected++; } } return cumulativeDataRowsAffected; }
private int UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, int commandCount) { Debug.Assert(null != rowUpdatedEvent, "null rowUpdatedEvent"); int cumulativeDataRowsAffected = 0; switch (rowUpdatedEvent.Status) { case UpdateStatus.Continue: cumulativeDataRowsAffected = UpdatedRowStatusContinue(rowUpdatedEvent, batchCommands, commandCount); break; // return to foreach DataRow case UpdateStatus.ErrorsOccurred: cumulativeDataRowsAffected = UpdatedRowStatusErrors(rowUpdatedEvent, batchCommands, commandCount); break; // no datarow affected if ErrorsOccured case UpdateStatus.SkipCurrentRow: case UpdateStatus.SkipAllRemainingRows: // cancel the Update method cumulativeDataRowsAffected = UpdatedRowStatusSkip(batchCommands, commandCount); break; // foreach DataRow without accepting changes on this row (but user may haved accepted chagnes for us) default: throw ADP.InvalidUpdateStatus(rowUpdatedEvent.Status); } // switch RowUpdatedEventArgs.Status return cumulativeDataRowsAffected; }
private int UpdatedRowStatusContinue(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, int commandCount) { Debug.Assert(null != batchCommands, "null batchCommands?"); int cumulativeDataRowsAffected = 0; // 1. We delay accepting the changes until after we fire RowUpdatedEvent // so the user has a chance to call RejectChanges for any given reason // 2. If the DataSource return 0 records affected, its an indication that // the command didn't take so we don't want to automatically // AcceptChanges. // With 'set nocount on' the count will be -1, accept changes in that case too. // 3. Don't accept changes if no rows were affected, the user needs // to know that there is a concurrency violation // Only accept changes if the row is not already accepted, ie detached. bool acdu = AcceptChangesDuringUpdate; for (int i = 0; i < commandCount; i++) { DataRow row = batchCommands[i]._row; if ((null == batchCommands[i]._errors) && batchCommands[i]._recordsAffected.HasValue && (0 != batchCommands[i]._recordsAffected.Value)) { Debug.Assert(null != row, "null dataRow?"); if (acdu) { if (0 != ((DataRowState.Added | DataRowState.Deleted | DataRowState.Modified) & row.RowState)) { row.AcceptChanges(); } } cumulativeDataRowsAffected++; } } return cumulativeDataRowsAffected; }
protected virtual int Update(DataRow[] dataRows, DataTableMapping tableMapping) { int num10; IntPtr ptr; Bid.ScopeEnter(out ptr, "<comm.DbDataAdapter.Update|API> %d#, dataRows[], tableMapping", base.ObjectID); try { int num3 = 0; IDbConnection[] connections = new IDbConnection[5]; ConnectionState[] connectionStates = new ConnectionState[5]; bool useSelectConnectionState = false; IDbCommand selectCommand = this._IDbDataAdapter.SelectCommand; if (selectCommand != null) { connections[0] = selectCommand.Connection; if (connections[0] != null) { connectionStates[0] = connections[0].State; useSelectConnectionState = true; } } int length = Math.Min(this.UpdateBatchSize, dataRows.Length); if (length < 1) { length = dataRows.Length; } BatchCommandInfo[] batchCommands = new BatchCommandInfo[length]; DataRow[] rowArray = new DataRow[length]; int index = 0; try { try { if (1 != length) { this.InitializeBatching(); } StatementType select = StatementType.Select; IDbCommand insertCommand = null; foreach (DataRow row in dataRows) { if (row == null) { continue; } bool isRowUpdatingCommand = false; switch (row.RowState) { case DataRowState.Detached: case DataRowState.Unchanged: { continue; } case DataRowState.Added: select = StatementType.Insert; insertCommand = this._IDbDataAdapter.InsertCommand; break; case DataRowState.Deleted: select = StatementType.Delete; insertCommand = this._IDbDataAdapter.DeleteCommand; break; case DataRowState.Modified: select = StatementType.Update; insertCommand = this._IDbDataAdapter.UpdateCommand; break; default: throw ADP.InvalidDataRowState(row.RowState); } RowUpdatingEventArgs args3 = this.CreateRowUpdatingEvent(row, insertCommand, select, tableMapping); try { row.RowError = null; if (insertCommand != null) { this.ParameterInput(insertCommand.Parameters, select, row, tableMapping); } } catch (Exception exception5) { if (!ADP.IsCatchableExceptionType(exception5)) { throw; } ADP.TraceExceptionForCapture(exception5); args3.Errors = exception5; args3.Status = UpdateStatus.ErrorsOccurred; } this.OnRowUpdating(args3); IDbCommand command2 = args3.Command; isRowUpdatingCommand = insertCommand != command2; insertCommand = command2; command2 = null; UpdateStatus status = args3.Status; if (status != UpdateStatus.Continue) { if (UpdateStatus.ErrorsOccurred != status) { if (UpdateStatus.SkipCurrentRow != status) { if (UpdateStatus.SkipAllRemainingRows != status) { throw ADP.InvalidUpdateStatus(status); } if (DataRowState.Unchanged == row.RowState) { num3++; } break; } if (DataRowState.Unchanged == row.RowState) { num3++; } } else { this.UpdatingRowStatusErrors(args3, row); } continue; } args3 = null; RowUpdatedEventArgs args = null; if (1 == length) { if (insertCommand != null) { batchCommands[0].CommandIdentifier = 0; batchCommands[0].ParameterCount = insertCommand.Parameters.Count; batchCommands[0].StatementType = select; batchCommands[0].UpdatedRowSource = insertCommand.UpdatedRowSource; } batchCommands[0].Row = row; rowArray[0] = row; index = 1; goto Label_0383; } Exception exception = null; try { if (insertCommand != null) { if ((UpdateRowSource.FirstReturnedRecord & insertCommand.UpdatedRowSource) == UpdateRowSource.None) { batchCommands[index].CommandIdentifier = this.AddToBatch(insertCommand); batchCommands[index].ParameterCount = insertCommand.Parameters.Count; batchCommands[index].Row = row; batchCommands[index].StatementType = select; batchCommands[index].UpdatedRowSource = insertCommand.UpdatedRowSource; rowArray[index] = row; index++; if (index >= length) { goto Label_0314; } continue; } exception = ADP.ResultsNotAllowedDuringBatch(); } else { exception = ADP.UpdateRequiresCommand(select, isRowUpdatingCommand); } } catch (Exception exception4) { if (!ADP.IsCatchableExceptionType(exception4)) { throw; } ADP.TraceExceptionForCapture(exception4); exception = exception4; } Label_0314: if (exception != null) { args = this.CreateRowUpdatedEvent(row, insertCommand, StatementType.Batch, tableMapping); args.Errors = exception; args.Status = UpdateStatus.ErrorsOccurred; this.OnRowUpdated(args); if (exception != args.Errors) { for (int j = 0; j < batchCommands.Length; j++) { batchCommands[j].Errors = null; } } num3 += this.UpdatedRowStatus(args, batchCommands, index); if (UpdateStatus.SkipAllRemainingRows != args.Status) { continue; } break; } Label_0383: args = this.CreateRowUpdatedEvent(row, insertCommand, select, tableMapping); try { if (1 != length) { IDbConnection connection3 = GetConnection1(this); ConnectionState state = this.UpdateConnectionOpen(connection3, StatementType.Batch, connections, connectionStates, useSelectConnectionState); args.AdapterInit(rowArray); if (ConnectionState.Open == state) { this.UpdateBatchExecute(batchCommands, index, args); } else { args.Errors = ADP.UpdateOpenConnectionRequired(StatementType.Batch, false, state); args.Status = UpdateStatus.ErrorsOccurred; } } else if (insertCommand != null) { IDbConnection connection2 = GetConnection4(this, insertCommand, select, isRowUpdatingCommand); ConnectionState state3 = this.UpdateConnectionOpen(connection2, select, connections, connectionStates, useSelectConnectionState); if (ConnectionState.Open == state3) { this.UpdateRowExecute(args, insertCommand, select); batchCommands[0].RecordsAffected = new int?(args.RecordsAffected); batchCommands[0].Errors = null; } else { args.Errors = ADP.UpdateOpenConnectionRequired(select, isRowUpdatingCommand, state3); args.Status = UpdateStatus.ErrorsOccurred; } } else { args.Errors = ADP.UpdateRequiresCommand(select, isRowUpdatingCommand); args.Status = UpdateStatus.ErrorsOccurred; } } catch (Exception exception3) { if (!ADP.IsCatchableExceptionType(exception3)) { throw; } ADP.TraceExceptionForCapture(exception3); args.Errors = exception3; args.Status = UpdateStatus.ErrorsOccurred; } bool flag3 = UpdateStatus.ErrorsOccurred == args.Status; Exception errors = args.Errors; this.OnRowUpdated(args); if (errors != args.Errors) { for (int k = 0; k < batchCommands.Length; k++) { batchCommands[k].Errors = null; } } num3 += this.UpdatedRowStatus(args, batchCommands, index); if (UpdateStatus.SkipAllRemainingRows == args.Status) { if (flag3 && (1 != length)) { this.ClearBatch(); index = 0; } break; } if (1 != length) { this.ClearBatch(); index = 0; } for (int i = 0; i < batchCommands.Length; i++) { batchCommands[i] = new BatchCommandInfo(); } index = 0; } if ((1 != length) && (0 < index)) { RowUpdatedEventArgs rowUpdatedEvent = this.CreateRowUpdatedEvent(null, insertCommand, select, tableMapping); try { IDbConnection connection = GetConnection1(this); ConnectionState state2 = this.UpdateConnectionOpen(connection, StatementType.Batch, connections, connectionStates, useSelectConnectionState); DataRow[] destinationArray = rowArray; if (index < rowArray.Length) { destinationArray = new DataRow[index]; Array.Copy(rowArray, destinationArray, index); } rowUpdatedEvent.AdapterInit(destinationArray); if (ConnectionState.Open == state2) { this.UpdateBatchExecute(batchCommands, index, rowUpdatedEvent); } else { rowUpdatedEvent.Errors = ADP.UpdateOpenConnectionRequired(StatementType.Batch, false, state2); rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } } catch (Exception exception2) { if (!ADP.IsCatchableExceptionType(exception2)) { throw; } ADP.TraceExceptionForCapture(exception2); rowUpdatedEvent.Errors = exception2; rowUpdatedEvent.Status = UpdateStatus.ErrorsOccurred; } Exception exception6 = rowUpdatedEvent.Errors; this.OnRowUpdated(rowUpdatedEvent); if (exception6 != rowUpdatedEvent.Errors) { for (int m = 0; m < batchCommands.Length; m++) { batchCommands[m].Errors = null; } } num3 += this.UpdatedRowStatus(rowUpdatedEvent, batchCommands, index); } } finally { if (1 != length) { this.TerminateBatching(); } } } finally { for (int n = 0; n < connections.Length; n++) { QuietClose(connections[n], connectionStates[n]); } } num10 = num3; } finally { Bid.ScopeLeave(ref ptr); } return num10; }
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 int UpdatedRowStatusSkip(BatchCommandInfo[] batchCommands, int commandCount) { int num2 = 0; for (int i = 0; i < commandCount; i++) { DataRow row = batchCommands[i].Row; if (((DataRowState.Unchanged | DataRowState.Detached) & row.RowState) != 0) { num2++; } } return num2; }
private int UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, int commandCount) { Exception errors = rowUpdatedEvent.Errors; if (errors == null) { errors = ADP.RowUpdatedErrors(); rowUpdatedEvent.Errors = errors; } int num3 = 0; bool flag = false; string message = errors.Message; for (int i = 0; i < commandCount; i++) { DataRow row = batchCommands[i].Row; if (batchCommands[i].Errors != null) { string str = batchCommands[i].Errors.Message; if (string.IsNullOrEmpty(str)) { str = message; } row.RowError = row.RowError + str; flag = true; } } if (!flag) { for (int j = 0; j < commandCount; j++) { batchCommands[j].Row.RowError = batchCommands[j].Row.RowError + message; } } else { num3 = this.UpdatedRowStatusContinue(rowUpdatedEvent, batchCommands, commandCount); } if (!base.ContinueUpdateOnError) { throw errors; } return num3; }
private int UpdatedRowStatusContinue(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, int commandCount) { int num2 = 0; bool acceptChangesDuringUpdate = base.AcceptChangesDuringUpdate; for (int i = 0; i < commandCount; i++) { DataRow row = batchCommands[i].Row; if (((batchCommands[i].Errors == null) && batchCommands[i].RecordsAffected.HasValue) && (batchCommands[i].RecordsAffected.Value != 0)) { if (acceptChangesDuringUpdate && (((DataRowState.Modified | DataRowState.Deleted | DataRowState.Added) & row.RowState) != 0)) { row.AcceptChanges(); } num2++; } } return num2; }
private int UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, int commandCount) { switch (rowUpdatedEvent.Status) { case UpdateStatus.Continue: return this.UpdatedRowStatusContinue(rowUpdatedEvent, batchCommands, commandCount); case UpdateStatus.ErrorsOccurred: return this.UpdatedRowStatusErrors(rowUpdatedEvent, batchCommands, commandCount); case UpdateStatus.SkipCurrentRow: case UpdateStatus.SkipAllRemainingRows: return this.UpdatedRowStatusSkip(batchCommands, commandCount); } throw ADP.InvalidUpdateStatus(rowUpdatedEvent.Status); }
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; } }