Given this oracle stored proc package:
CREATE OR REPLACE
PACKAGE TESTPKG AS
FUNCTION TestReturnRefCursor RETURN SYS_REFCURSOR;
PROCEDURE TestingRefCursorsAsOutParam (outp OUT SYS_REFCURSOR);
END TESTPKG
And this package body:
CREATE OR REPLACE
PACKAGE BODY TESTPKG AS
FUNCTION TestReturnRefCursor RETURN SYS_REFCURSOR AS
outp SYS_REFCURSOR;
BEGIN
OPEN outp FOR SELECT * FROM TABLENAME;
RETURN outp;
END TestReturnRefCursor;
PROCEDURE TestingRefCursorsAsOutParam (outp OUT SYS_REFCURSOR) AS
BEGIN
OPEN outp FOR SELECT * FROM TABLENAME;
END TestingRefCursorsAsOutParam;
END TESTPKG;
I am trying to use Dapper to call either function. I have created the OracleDynamicParameters class that implements Dapper.SqlMapper.IDynamicParameters that I found at this post after searching StackOverflow: https://gist.github.com/vijaysg/3096151
Calling the TestReturnRefCursor stored function works fine with this code:
var conn = new OracleConnection(ConfigurationManager.ConnectionStrings["DataConnection"].ConnectionString);
conn.Open();
var p = new OracleDynamicParameters();
p.Add("retSet", dbType: OracleDbType.RefCursor, direction: ParameterDirection.ReturnValue);
conn.Execute("TESTPKG.TestReturnRefCursor ", param: p, commandType: CommandType.StoredProcedure);
var refcur = p.Get<OracleRefCursor>("retSet");
// do something with refcur
conn.Close();
However, when I try to call the TestingRefCursorsAsOutParam stored procedure with this code:
var conn = new OracleConnection(ConfigurationManager.ConnectionStrings["DataConnection"].ConnectionString);
conn.Open();
var p = new OracleDynamicParameters();
p.Add("retSet", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output);
conn.Execute("TESTPKG.TestingRefCursorsAsOutParam ", param: p, commandType: CommandType.StoredProcedure);
var refcur = p.Get<OracleRefCursor>("retSet");
// do something with refcur
conn.Close();
I get an OracleException from the Oracle.ManagedDataAccess.dll with the detail:
"ORA-06550: line 1, column 7:\nPLS-00306: wrong number or types of arguments in call to 'TESTINGREFCURSORSASOUTPARAM'\nORA-06550: line 1, column 7:\nPL/SQL: Statement ignored"
I found after searching another stackoverflow post where sometimes parameters aren't bound if they are null unless you specifically set their value to be DBNull.Value, so I tried changing the add parameter line to be:
p.Add("retSet", value: DBNull.Value, dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output);
but this did not help.
I can call this stored procedure just fine using regular c# oracle code:
var cmd = conn.CreateCommand();
cmd.CommandText = "TESTPKG.TestingRefCursorsAsOutParam";
cmd.CommandType = CommandType.StoredProcedure;
var outparam = new OracleParameter();
outparam.ParameterName = "retSet";
outparam.Direction = ParameterDirection.Output;
outparam.OracleDbType = OracleDbType.RefCursor;
cmd.Parameters.Add(outparam);
OracleDataAdapter da = new OracleDataAdapter(cmd);
cmd.ExecuteNonQuery();
var refcur = (OracleRefCursor)cmd.Parameters[0].Value;
Is there something I am missing here, or is Dapper not functioning correctly?
If you do not want to use a strong type for your result using dapper (i.e: Query<YourStrongType>
), you can use Query<dynamic>
, the code below should work:
IEnumerable<dynamic> results = null;
using (var conn = new OracleConnection(ConfigurationManager.ConnectionStrings["DataConnection"].ConnectionString))
{
var p = new OracleDynamicParameters();
p.Add("outp ", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output);
results = conn.Query<dynamic>("TESTPKG.TestingRefCursorsAsOutParam", p, commandType: CommandType.StoredProcedure);
foreach (var row in results)
{
var fields = row as IDictionary<string, object>;
}
}