/// <include file='docs/mysqlcommand.xml' path='docs/ExecuteReader1/*'/>
public new MySqlDataReader ExecuteReader(CommandBehavior behavior)
{
// give our interceptors a shot at it first
MySqlDataReader interceptedReader = null;
if (connection?.commandInterceptor != null && connection.commandInterceptor.ExecuteReader(CommandText, behavior, ref interceptedReader))
{
return(interceptedReader);
}
// interceptors didn't handle this so we fall through
bool success = false;
CheckState();
Driver driver = connection.driver;
cmdText = cmdText.Trim();
if (String.IsNullOrEmpty(cmdText))
{
Throw(new InvalidOperationException(Resources.CommandTextNotInitialized));
}
string sql = cmdText.Trim(';');
#if !NETSTANDARD1_3
// Load balancing getting a new connection
if (connection.hasBeenOpen && !driver.HasStatus(ServerStatusFlags.InTransaction))
{
ReplicationManager.GetNewConnection(connection.Settings.Server, !IsReadOnlyCommand(sql), connection);
}
#endif
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 !NETSTANDARD1_3
System.Transactions.Transaction curTrans = System.Transactions.Transaction.Current;
if (curTrans != null)
{
bool inRollback = false;
//TODO: ADD support for 452 and 46X
if (driver.currentTransaction != null)
{
inRollback = driver.currentTransaction.InRollback;
}
if (!inRollback)
{
System.Transactions.TransactionStatus status = System.Transactions.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 (System.Transactions.TransactionException)
{
}
if (status == System.Transactions.TransactionStatus.Aborted)
{
Throw(new System.Transactions.TransactionAbortedException());
}
}
}
#endif
commandTimer = new CommandTimer(connection, CommandTimeout);
LastInsertedId = -1;
if (CommandType == CommandType.TableDirect)
{
sql = "SELECT * FROM " + sql;
}
else if (CommandType == CommandType.Text)
{
// validates single word statetment (maybe is a stored procedure call)
if (sql.IndexOf(" ") == -1)
{
if (AddCallStatement(sql))
{
sql = "call " + 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);
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
}
#if !NETSTANDARD1_3
catch (ThreadAbortException taex)
{
connection.HandleTimeoutOrThreadAbort(taex);
throw;
}
#endif
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();
}
}
}
}
}