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);
}
#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;
if (cmdText == null ||
cmdText.Trim().Length == 0)
throw new InvalidOperationException(Resources.CommandTextNotInitialized);
string sql = TrimSemicolons(cmdText);
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;
// 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 (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();
}
}
}
}
}