예제 #1
0
        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);
            }
        }
예제 #2
0
        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
        }
예제 #3
0
        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;
        }
예제 #4
0
 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;
 }
예제 #5
0
        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;
        }
예제 #7
0
        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;
     }
 }