1- Connect to a Oracle XE using Oracle.DataAccess
2- Execute a command to add a column to a table: alter table TABLE add COLUMN b int;
3- Execute a command to select this column
4- Read with a DataReader. Application raises IndexOutOfRangeException: Unable to find specified column in result set
5- Restart the application and the query runs correctly
Why DataReader can’t access the column I have created just now?
Here is a large but simple code to test:
private void button1_Click(object sender, EventArgs e)
{
using (OracleConnection con = new OracleConnection(Settings.Default.CS))
{
con.Open();
try
{
using (OracleCommand com = new OracleCommand())
{
com.Connection = con;
// Create a test table
com.CommandText = "CREATE TABLE Test (a int)";
com.ExecuteNonQuery();
// Add one column
com.CommandText = "ALTER TABLE Test ADD b int";
com.ExecuteNonQuery();
com.CommandText = "SELECT * FROM Test";
using (DbDataReader dr = com.ExecuteReader())
{
MessageBox.Show(dr.FieldCount.ToString());
// Here is showing "2", thats ok
}
}
}
finally
{
con.Close();
}
}
}
private void button2_Click(object sender, EventArgs e)
{
using (OracleConnection con = new OracleConnection(Settings.Default.CS))
{
con.Open();
try
{
using (OracleCommand com = new OracleCommand())
{
OracleTransaction trans = con.BeginTransaction();
try
{
// Add a column to table already created
com.Connection = con;
com.CommandText = "ALTER TABLE Test ADD c int";
com.ExecuteNonQuery();
// Insert a value, ok
com.CommandText = "INSERT INTO TEST (a, b, c) VALUES (1, 2, 3)";
com.ExecuteNonQuery();
trans.Commit();
}
catch
{
trans.Rollback();
throw;
}
// Selecting only "c" column
com.CommandText = "SELECT c FROM Test";
using (DbDataReader dr = com.ExecuteReader())
{
if (dr.Read())
MessageBox.Show(Convert.ToInt32(dr["c"]).ToString());
// Showing correct value, ok
}
// Uncomment these lines to solve problem
//con.Close();
//OracleConnection.ClearAllPools();
//con.Open();
// Selecting all fields * from table
com.CommandText = "SELECT * FROM Test";
using (DbDataReader dr = com.ExecuteReader())
{
MessageBox.Show(dr.GetSchemaTable().Rows.Count.ToString() + " / " + dr.FieldCount.ToString());
// HERE IS THE PROBLEM: message are showing 2/2, but table haves 3 fields
if (dr.Read())
MessageBox.Show(Convert.ToInt32(dr["c"]).ToString());
// Here throws IndexOutOfRangeException: Unable to find specified column in result set
}
}
}
finally
{
con.Close();
}
}
}
It sounds like the insert transaction is not committed yet when you execute the reader. I’m thinking you could verify this by closing the connection just after you insert and open it again just before you execute the reader (you may need to use OracleConnection.ClearAllPools)