有人在社区问到:C#调用Oracle中自定义函数的返回值时,无法正常调用。但在PL/SQL中正常调用返回。
于是动手一试:
1、准备函数(Oralce 11g.2.0.0.4)
1CREATE OR REPLACE FUNCTION F_Update_Grade(v_UserID in Number) 2 return nvarchar2 is 3 V_Grade nVARCHAR2(20); 4begin 5 V_Grade := '1205'; 6 update TESTDB3 set Grade = V_Grade where PKID = v_UserID; 7 commit; 8 return (V_Grade); 9end F_Update_Grade;
正常调用返回:
1declare 2 V_Result nvarchar2(1000) := ''; 3 V_UserID number(10) := 1; 4begin 5 V_Result := f_update_grade(V_UserID); 6 dbms_output.put_line('Value:' || V_Result); 7end; 8 9/* 10Value:1205 11*/
2、C#环境准备:(VS2019 社区版)
1)准备Oracle.ManagedDataAccess.Client,在Nuget管理器中搜索Oralce,并安装Oracle.ManagedDataAccess最新稳定版19.5

2、核心访问代码:
1 1 using Oracle.ManagedDataAccess.Client; 2 2 using System; 3 3 using System.Data; 4 4 using System.Data.SqlClient; 5 5 6 6 namespace TestOracle_ManagedDataAccess 7 7 { 8 8 class Program 9 9 { 1010 static void Main(string[] args) 1111 { 1212 TestFUNCTION3(); 1313 Console.ReadLine(); 1414 } 1515 1616 static void TestFUNCTION3() 1717 { 1818 string strConn = "Data Source=127.0.0.1/BCS;User ID=user2019;Password=password9102"; 1919 //OracleConnection objConn = new OracleConnection(strConn); 2020 string strFun = "F_Update_Grade"; 2121 //string strFun = "F_Get_Grade"; 2222 using (OracleConnection objConn = new OracleConnection(strConn)) 2323 { 2424 using (OracleCommand cmd = new OracleCommand(strFun, objConn)) 2525 { 2626 try 2727 { 2828 // 获取选中行 2929 //int strRowIdex = 1; 3030 3131 // 创建参数对象 3232 OracleParameter p1 = new OracleParameter("v_UserID", OracleDbType.Int32, ParameterDirection.Input); 3333 OracleParameter p2 = new OracleParameter("V_Grade", OracleDbType.NVarchar2, 20); 3434 p1.Value = 1;//取PKID为1的记录 3535 p2.Direction = ParameterDirection.ReturnValue; 3636 // 更新数据库表 3737 cmd.CommandType = CommandType.StoredProcedure; 3838 objConn.Open(); 3939 4040 /*************************************************************** 4141 * 注意,输出参数一定要第一个加,函数的返回值也是赋给第一个参数*; 4242 * *************************************************************/ 4343 cmd.Parameters.Add(p1); 4444 cmd.Parameters.Add(p2); 4545 cmd.ExecuteNonQuery(); 4646 4747 //返回结果值 4848 Console.WriteLine("V_Grade is :" + p2.Value.ToString()); 4949 Console.WriteLine("OK"); 5050 } 5151 catch (SqlException ex) 5252 { 5353 objConn.Close(); 5454 Console.WriteLine("ERROR in :" + ex.Message); 5555 } 5656 finally 5757 { 5858 cmd.Dispose(); 5959 objConn.Close(); 6060 } 6161 } 6262 } 6363 }
运行调试,没报错,但也没有更新数据表,注意:在执行前先将原数据表中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?