/// <include file='docs/mysqlcommand.xml' path='docs/ExecuteReader1/*'/> private void InnerBeginExecuteReader(CommandBehavior behavior) { lastInsertedId = -1; CheckState(); if (cmdText == null || cmdText.Trim().Length == 0) throw new InvalidOperationException(Resources.CommandTextNotInitialized); string sql = TrimSemicolons(cmdText); // now we check to see if we are executing a query that is buggy // in 4.1 connection.IsExecutingBuggyQuery = false; if (!connection.driver.Version.isAtLeast(5, 0, 0) && connection.driver.Version.isAtLeast(4, 1, 0)) { string snippet = sql; if (snippet.Length > 17) snippet = sql.Substring(0, 17); snippet = snippet.ToLower(CultureInfo.InvariantCulture); connection.IsExecutingBuggyQuery = snippet.StartsWith("describe") || snippet.StartsWith("show table status"); } 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(); // 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); // start a threading timer on our command timeout timedOut = false; canceled = false; // execute the statement statement.Execute(); // start a timeout timer if (connection.driver.Version.isAtLeast(5, 0, 0) &&commandTimeout > 0) { ExecuteQueryManager.Instace.Add(this); } reader.BeginNextResult(); MysqlAsyncResult result = _asyncResult as MysqlAsyncResult; result.DataReader = reader; } catch (MySqlException ex) { if (ex.IsFatal) Connection.Close(); if (ex.Number == 0) throw new MySqlException(Resources.FatalErrorDuringExecute, ex); throw; } }
/// <include file='docs/mysqlcommand.xml' path='docs/ExecuteReader1/*'/> private void InnerBeginExecuteReader(CommandBehavior behavior) { 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); } #if !CF 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(); } } #endif 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 (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.BeginNextResult(); MysqlAsyncResult result = _asyncResult as MysqlAsyncResult; result.DataReader = 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 //只有主动调用Cancel时才会出现这个异常,注释让他throw吧 //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(); } } } } }