使用带有 C# 的 Dapper 以 refcursor 作为 out 参数调用 Oracle 存储过程时出现问题,但是 refcursor 作为 return 值有效
Issue using Dapper with C# to call an Oracle stored proc with refcursor as out parameter, however refcursor as return value works
鉴于此 oracle 存储过程包:
CREATE OR REPLACE
PACKAGE TESTPKG AS
FUNCTION TestReturnRefCursor RETURN SYS_REFCURSOR;
PROCEDURE TestingRefCursorsAsOutParam (outp OUT SYS_REFCURSOR);
END TESTPKG
还有这个包体:
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;
我正在尝试使用 Dapper 调用任一函数。我创建了实现 Dapper.SqlMapper.IDynamicParameters 的 OracleDynamicParameters class,我在搜索 Whosebug 后在此 post 找到:https://gist.github.com/vijaysg/3096151
调用 TestReturnRefCursor 存储函数可以正常使用此代码:
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();
但是,当我尝试使用以下代码调用 TestingRefCursorsAsOutParam 存储过程时:
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();
我从 Oracle.ManagedDataAccess.dll 中得到一个 OracleException,详细信息:
"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"
我在搜索另一个 Whosebug post 后发现,如果参数为 null,有时参数不会被绑定,除非你专门将它们的值设置为 DBNull.Value,所以我尝试将添加参数行更改为是:
p.Add("retSet", value: DBNull.Value, dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output);
但这并没有帮助。
我可以使用常规的 c# oracle 代码调用此存储过程:
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;
是不是我遗漏了什么,或者 Dapper 没有正常运行?
如果您不想使用 dapper 为您的结果使用强类型(即:Query<YourStrongType>
),您可以使用 Query<dynamic>
,下面的代码应该有效:
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>;
}
}
鉴于此 oracle 存储过程包:
CREATE OR REPLACE
PACKAGE TESTPKG AS
FUNCTION TestReturnRefCursor RETURN SYS_REFCURSOR;
PROCEDURE TestingRefCursorsAsOutParam (outp OUT SYS_REFCURSOR);
END TESTPKG
还有这个包体:
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;
我正在尝试使用 Dapper 调用任一函数。我创建了实现 Dapper.SqlMapper.IDynamicParameters 的 OracleDynamicParameters class,我在搜索 Whosebug 后在此 post 找到:https://gist.github.com/vijaysg/3096151
调用 TestReturnRefCursor 存储函数可以正常使用此代码:
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();
但是,当我尝试使用以下代码调用 TestingRefCursorsAsOutParam 存储过程时:
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();
我从 Oracle.ManagedDataAccess.dll 中得到一个 OracleException,详细信息:
"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"
我在搜索另一个 Whosebug post 后发现,如果参数为 null,有时参数不会被绑定,除非你专门将它们的值设置为 DBNull.Value,所以我尝试将添加参数行更改为是:
p.Add("retSet", value: DBNull.Value, dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output);
但这并没有帮助。
我可以使用常规的 c# oracle 代码调用此存储过程:
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;
是不是我遗漏了什么,或者 Dapper 没有正常运行?
如果您不想使用 dapper 为您的结果使用强类型(即:Query<YourStrongType>
),您可以使用 Query<dynamic>
,下面的代码应该有效:
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>;
}
}