Exemplo n.º 1
0
        /// <include file='docs/mysqlcommand.xml' path='docs/ExecuteReader1/*'/>
        public new MySqlDataReader ExecuteReader(CommandBehavior behavior)
        {
            bool success = false;

            CheckState();
            Driver driver = connection.driver;

            lock (driver)
            {
                // We have to recheck that there is no reader, after we got the lock
                if (connection.Reader != null)
                {
                    throw new MySqlException(Resources.DataReaderOpen);
                }
                System.Transactions.Transaction curTrans = System.Transactions.Transaction.Current;
                if (curTrans != null)
                {
                    bool inRollback = false;
                    if (driver.CurrentTransaction != null)
                    {
                        inRollback = driver.CurrentTransaction.InRollback;
                    }
                    if (!inRollback)
                    {
                        TransactionStatus status = TransactionStatus.InDoubt;
                        try
                        {
                            // in some cases (during state transitions) this throws
                            // an exception. Ignore exceptions, we're only interested
                            // whether transaction was aborted or not.
                            status = curTrans.TransactionInformation.Status;
                        }
                        catch (TransactionException)
                        {
                        }
                        if (status == TransactionStatus.Aborted)
                        {
                            throw new TransactionAbortedException();
                        }
                    }
                }

                commandTimer = new CommandTimer(connection, CommandTimeout);

                lastInsertedId = -1;
                cmdText        = cmdText.Trim();
                if (String.IsNullOrEmpty(cmdText))
                {
                    throw new InvalidOperationException(Resources.CommandTextNotInitialized);
                }

                string sql = cmdText.Trim(';');

                if (CommandType == CommandType.TableDirect)
                {
                    sql = "SELECT * FROM " + sql;
                }

                // if we are on a replicated connection, we are only allow readonly statements
                if (connection.Settings.Replication && !InternallyCreated)
                {
                    EnsureCommandIsReadOnly(sql);
                }

                if (statement == null || !statement.IsPrepared)
                {
                    if (CommandType == CommandType.StoredProcedure)
                    {
                        statement = new StoredProcedure(this, sql);
                    }
                    else
                    {
                        statement = new PreparableStatement(this, sql);
                    }
                }

                // stored procs are the only statement type that need do anything during resolve
                statement.Resolve(false);

                // Now that we have completed our resolve step, we can handle our
                // command behaviors
                HandleCommandBehaviors(behavior);

                updatedRowCount = -1;
                try
                {
                    MySqlDataReader reader = new MySqlDataReader(this, statement, behavior);
                    connection.Reader = reader;
                    canceled          = false;
                    // execute the statement
                    statement.Execute();
                    // wait for data to return
                    reader.NextResult();
                    success = true;
                    return(reader);
                }
                catch (TimeoutException tex)
                {
                    connection.HandleTimeoutOrThreadAbort(tex);
                    throw; //unreached
                }
                catch (ThreadAbortException taex)
                {
                    connection.HandleTimeoutOrThreadAbort(taex);
                    throw;
                }
                catch (IOException ioex)
                {
                    connection.Abort(); // Closes connection without returning it to the pool
                    throw new MySqlException(Resources.FatalErrorDuringExecute, ioex);
                }
                catch (MySqlException ex)
                {
                    if (ex.InnerException is TimeoutException)
                    {
                        throw; // already handled
                    }
                    try
                    {
                        ResetReader();
                        ResetSqlSelectLimit();
                    }
                    catch (Exception)
                    {
                        // Reset SqlLimit did not work, connection is hosed.
                        Connection.Abort();
                        throw new MySqlException(ex.Message, true, ex);
                    }

                    // if we caught an exception because of a cancel, then just return null
                    if (ex.IsQueryAborted)
                    {
                        return(null);
                    }
                    if (ex.IsFatal)
                    {
                        Connection.Close();
                    }
                    if (ex.Number == 0)
                    {
                        throw new MySqlException(Resources.FatalErrorDuringExecute, ex);
                    }
                    throw;
                }
                finally
                {
                    if (connection != null)
                    {
                        if (connection.Reader == null)
                        {
                            // Something went seriously wrong,  and reader would not
                            // be able to clear timeout on closing.
                            // So we clear timeout here.
                            ClearCommandTimer();
                        }
                        if (!success)
                        {
                            // ExecuteReader failed.Close Reader and set to null to
                            // prevent subsequent errors with DataReaderOpen
                            ResetReader();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Advances the data reader to the next result, when reading the results of batch SQL statements.
        /// </summary>
        /// <returns></returns>
        public override bool NextResult()
        {
            if (!isOpen)
            {
                throw new MySqlException(Resources.NextResultIsClosed);
            }

            bool isCaching = command.CommandType == CommandType.TableDirect && command.EnableCaching &&
                             (commandBehavior & CommandBehavior.SequentialAccess) == 0;

            // this will clear out any unread data
            if (resultSet != null)
            {
                resultSet.Close();
                if (isCaching)
                {
                    TableCache.AddToCache(command.CommandText, resultSet);
                }
            }

            // single result means we only return a single resultset.  If we have already
            // returned one, then we return false
            // TableDirect is basically a select * from a single table so it will generate
            // a single result also
            if (resultSet != null &&
                ((commandBehavior & CommandBehavior.SingleResult) != 0 || isCaching))
            {
                return(false);
            }

            // next load up the next resultset if any
            try
            {
                do
                {
                    resultSet = null;
                    // if we are table caching, then try to retrieve the resultSet from the cache
                    if (isCaching)
                    {
                        resultSet = TableCache.RetrieveFromCache(command.CommandText,
                                                                 command.CacheAge);
                    }

                    if (resultSet == null)
                    {
                        resultSet = driver.NextResult(Statement.StatementId, false);
                        if (resultSet == null)
                        {
                            return(false);
                        }
                        if (resultSet.IsOutputParameters && command.CommandType == CommandType.StoredProcedure)
                        {
                            StoredProcedure sp = statement as StoredProcedure;
                            sp.ProcessOutputParameters(this);
                            resultSet.Close();
                            if (!sp.ServerProvidingOutputParameters)
                            {
                                return(false);
                            }
                            // if we are using server side output parameters then we will get our ok packet
                            // *after* the output parameters resultset
                            resultSet = driver.NextResult(Statement.StatementId, true);
                        }
                        resultSet.Cached = isCaching;
                    }

                    if (resultSet.Size == 0)
                    {
                        Command.lastInsertedId = resultSet.InsertedId;
                        if (affectedRows == -1)
                        {
                            affectedRows = resultSet.AffectedRows;
                        }
                        else
                        {
                            affectedRows += resultSet.AffectedRows;
                        }
                    }
                } while (resultSet.Size == 0);

                return(true);
            }
            catch (MySqlException ex)
            {
                if (ex.IsFatal)
                {
                    connection.Abort();
                }
                if (ex.Number == 0)
                {
                    throw new MySqlException(Resources.FatalErrorReadingResult, ex);
                }
                if ((commandBehavior & CommandBehavior.CloseConnection) != 0)
                {
                    Close();
                }
                throw;
            }
        }