有人在社區問到:C#調用Oracle中自定義函數的返回值時,無法正常調用。但在PL/SQL中正常調用返回。 ...
有人在社區問到:C#調用Oracle中自定義函數的返回值時,無法正常調用。但在PL/SQL中正常調用返回。
於是動手一試:
1、準備函數(Oralce 11g.2.0.0.4)
CREATE OR REPLACE FUNCTION F_Update_Grade(v_UserID in Number) return nvarchar2 is V_Grade nVARCHAR2(20); begin V_Grade := '1205'; update TESTDB3 set Grade = V_Grade where PKID = v_UserID; commit; return (V_Grade); end F_Update_Grade;
正常調用返回:
declare V_Result nvarchar2(1000) := ''; V_UserID number(10) := 1; begin V_Result := f_update_grade(V_UserID); dbms_output.put_line('Value:' || V_Result); end; /* Value:1205 */
2、C#環境準備:(VS2019 社區版)
1)準備Oracle.ManagedDataAccess.Client,在Nuget管理器中搜索Oralce,並安裝Oracle.ManagedDataAccess最新穩定版19.5
2、核心訪問代碼:
1 using Oracle.ManagedDataAccess.Client; 2 using System; 3 using System.Data; 4 using System.Data.SqlClient; 5 6 namespace TestOracle_ManagedDataAccess 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 TestFUNCTION3(); 13 Console.ReadLine(); 14 } 15 16 static void TestFUNCTION3() 17 { 18 string strConn = "Data Source=127.0.0.1/BCS;User ID=user2019;Password=password9102"; 19 //OracleConnection objConn = new OracleConnection(strConn); 20 string strFun = "F_Update_Grade"; 21 //string strFun = "F_Get_Grade"; 22 using (OracleConnection objConn = new OracleConnection(strConn)) 23 { 24 using (OracleCommand cmd = new OracleCommand(strFun, objConn)) 25 { 26 try 27 { 28 // 獲取選中行 29 //int strRowIdex = 1; 30 31 // 創建參數對象 32 OracleParameter p1 = new OracleParameter("v_UserID", OracleDbType.Int32, ParameterDirection.Input); 33 OracleParameter p2 = new OracleParameter("V_Grade", OracleDbType.NVarchar2, 20); 34 p1.Value = 1;//取PKID為1的記錄 35 p2.Direction = ParameterDirection.ReturnValue; 36 // 更新資料庫表 37 cmd.CommandType = CommandType.StoredProcedure; 38 objConn.Open(); 39 40 /*************************************************************** 41 * 註意,輸出參數一定要第一個加,函數的返回值也是賦給第一個參數*; 42 * *************************************************************/ 43 cmd.Parameters.Add(p1); 44 cmd.Parameters.Add(p2); 45 cmd.ExecuteNonQuery(); 46 47 //返回結果值 48 Console.WriteLine("V_Grade is :" + p2.Value.ToString()); 49 Console.WriteLine("OK"); 50 } 51 catch (SqlException ex) 52 { 53 objConn.Close(); 54 Console.WriteLine("ERROR in :" + ex.Message); 55 } 56 finally 57 { 58 cmd.Dispose(); 59 objConn.Close(); 60 } 61 } 62 } 63 }
運行調試,沒報錯,但也沒有更新數據表,註意:在執行前先將原數據表中Grade值更新為1,程式運行後Grade值仍為1。
update testdb3 set grade=1 where PKID=1;
跟蹤調試,發現參數值不對, p2.Direction = ParameterDirection.ReturnValue;,結果返回值給p1。
莫非,預設給的是第一個參數,調換p1,p2的順序,果然正常調用:
運行結果,數據表中的行也更新完成:
小結:
Oracle.ManagedDataAccess.Client調用有返回值的函數時, cmd.Parameters.Add的第一個參數一定要是ParameterDirection.ReturnValue。不確定這是不是一個bug?