2012-04-17 32 views
1

1-使用Oracle.DataAccess錯誤選擇欄最近與ALTER TABLE插入ODP.NET

2-執行一個命令將列添加到表連接到的Oracle XE:改變表TABLE添加塔B INT ;

3-執行命令以選擇此列

4-使用DataReader讀取。應用程序引發IndexOutOfRangeException:無法找到結果指定列設置

5重新啓動應用程序,查詢可以正常運行

DataReader的,爲什麼不能訪問我創建剛纔列?

這裏是一個大而簡單的代碼來測試:

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(); 
     } 
    } 
} 
+0

對我來說,這聽起來像某種元數據緩存。也許 'OracleConnection.PurgeStatementCache()'方法可以幫助嗎? – 2012-04-17 21:15:46

+0

我在添加列之後嘗試了PurgeStatementCache,然後再選擇,但沒有奏效。 – rkawano 2012-04-18 12:36:37

+0

'OracleTransaction'應該被丟棄,所以應該有它自己的'using'塊。您可以選擇使用['OracleCommand.CreateCommand'](http://docs.oracle.com/html/B28089_01/OracleConnectionClass.htm#i1001011),因爲這樣可以節省您需要自行將連接分配給命令。 – WhiteKnight 2012-04-18 20:26:00

回答

1

這聽起來像插入事務,當你執行讀者尚未提交。我想,你可以通過關閉您插入,然後再次打開它,你執行了讀者之前剛剛經過的連接進行驗證(您可能需要使用OracleConnection.ClearAllPools)

+0

在我們的真實應用程序中,我們使用的是交易,行爲完全相同。重新打開連接不能解決,但重新啓動應用程序解決。 – rkawano 2012-04-17 20:52:20

+0

這包括調用OracleConnection.ClearAllPools嗎?如果你們正在使用連接池,那麼即使你調用「close」,框架也會將連接對象保留在池中。 – Ulises 2012-04-17 21:05:34

+0

ClearAllPools工作正常!我執行命令添加列,關閉連接,執行clearAllPools並重新打開連接。工作得很好,我不需要重新啓動所有的應用程序。謝謝! – rkawano 2012-04-18 12:52:51

0

嘗試使用OracleConnection.BeginTransaction創建一個事務,然後Commit在選擇之前,如文檔中的example所示。

+0

我嘗試在添加列之前開始事務,並在插入值之後進行提交,但沒有奏效。 – rkawano 2012-04-18 13:10:31

+0

您能否編輯您的示例以顯示您對交易的使用? – WhiteKnight 2012-04-18 13:15:59

+0

編輯button2_Click – rkawano 2012-04-18 13:29:07