2016-07-25 38 views
0

這是我第一次不得不從C#調用Oracle存儲過程,我不知道爲什麼我的代碼不工作。我所要做的就是返回一個數據表。我的存儲過程編譯就好了 - 這裏是一些僞代碼描述它:從C#調用Oracle存儲過程的問題#

CREATE OR REPLACE PROCEDURE SPROC_ONLINE 
(Year IN NUMBER DEFAULT NULL 
, Name IN VARCHAR2 DEFAULT NULL 
, ID IN VARCHAR2 DEFAULT NULL 
, refCursor OUT SYS_REFCURSOR 
) 
AS 
BEGIN 
OPEN refCursor FOR 
SELECT * 
FROM TABLE 
WHERE Field_Year = Year 
    AND Field_Name = Name 
    AND Field_ID = ID; 
END SPROC_ONLINE; 

下面是一些僞代碼描述我的C#:

public static DataTable search(int? Year, string Name, string ID) 
    {    
     try 
     { 
      OracleConnection conn = getConnectionString();     
      OracleCommand cmd = new OracleCommand(); 
      cmd.Connection = conn; 
      cmd.CommandText = "SPROC_ONLINE"; 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("Year", OracleDbType.Int32).Value = Year; 
      cmd.Parameters.Add("Name", OracleDbType.Varchar2).Value = Name; 
      cmd.Parameters.Add("ID", OracleDbType.Varchar2).Value = ID;     
      cmd.Parameters.Add("Output", OracleDbType.RefCursor).Direction = ParameterDirection.Output; 

      DataTable dt = new DataTable(); 
      OracleDataAdapter da = new OracleDataAdapter(cmd); 
      getConnectionString().Open(); 
      cmd.ExecuteNonQuery(); 
      da.Fill(dt); 

      return dt;     
     } 
     catch (Exception e) { throw new Exception("Error: " + e.Message); } 
     finally { getConnectionString().Close(); } 
    } 

沒有錯誤被拋出;它只是返回的數據表是空的,當它不應該(我測試的參數應該返回的東西)。

我在做什麼錯在這裏?

+2

那ExecuteNonQuery在那裏沒有意義。刪除它 – Steve

+1

注意:我不確定'getConnectionString().' Close()'裏面的實現是什麼,但是如果它返回的是一個靜態連接,這將是不好的習慣。通常,您需要在需要時創建新的(不共享的)數據庫連接對象,並在完成時處理它。否則,如果您決定讓多個線程同時在數據庫中獨立執行某項操作,那麼稍後您將遇到問題。讓數據庫實現擔心集中連接(*我相信Oracle也可以在沒有太多問題的情況下處理這個問題*)。 – Igor

+0

@Igor - 感謝您的建議;你的評論讓我做了一些額外的研究。迄今爲止,我只在小應用程序上工作過,但我並沒有意識到這一點。非常感謝你。 – Jake

回答

0

我的問題結束了兩倍;這裏是我結束了後臺代碼:

public static DataTable search(int? Year, string Name, string ID) 
{ 
    try 
    { 
     using (var cmd = new OracleCommand("SPROC_ONLINE", getConnectionString())) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      var da = new OracleDataAdapter(cmd); 
      cmd.Parameters.Add("Year", OracleDbType.Int32).Value = Year; 
      cmd.Parameters.Add("Name", OracleDbType.Varchar2).Value = Name; 
      cmd.Parameters.Add("ID", OracleDbType.Varchar2).Value = ID; 
      cmd.Parameters.Add("Output", OracleDbType.RefCursor).Direction = ParameterDirection.Output; 
      DataTable dt = new DataTable(); 
      da.Fill(dt); 
      return dt; 
     } 
    } 
    catch (Exception e) {throw new Exception("Error: " + e); } 
    finally {} 
} 

我的另一個問題是,我不知道在Oracle中該字符串比較是區分大小寫的。顯然,在SQL Developer中編譯我的存儲過程並嘗試在Visual Studio中測試它之間,我並沒有始終輸入「Name」參數;這解釋了爲什麼返回空數據表。我調整我的存儲過程的WHERE子句如下:

WHERE Field_Year = Year 
    AND UPPER(Field_Name) = UPPER(Name) 
    AND Field_ID = ID; 

現在一切工作正常。

1

我想你可能需要使用OracleDataReader

using(OracleCommand cmd = new OracleCommand("SPROC_ONLINE", TheConnection)) 
{ 
    using(OracleDataReader reader = new OracleDataReader()) 
    { 
     while(reader.Read()) 
     { 
      // Extract the values 
      var a = reader["Year"]; 
      var b = reader["Name"]; 
      var c = reader["ID"]; 
      ... etc ... 
     } 
    } 
} 
+0

在這種情況下,我是否需要在while循環內動態創建數據表? – Jake

+0

@Jake:這是正確的。 – Ingenioushax