OracleCommand 添加 REF CURSOR 输出参数必须设 Direction = ParameterDirection.Output 且 OracleDbType.RefCursor,参数名严格匹配存储过程OUT名,仅 ExecuteReader() 可获取游标,托管驱动(Oracle.ManagedDataAccess)更可靠。
OracleCommand 添加 REF CURSOR 输出参数必须用 ParameterDirection.Output
ref cursor 在 oracle 里本质是服务端游标句柄,c# 无法直接“接收”它,必须靠 oracleparameter 显式声明为输出参数,并指定 oracledbtype.refcursor。漏设 direction 或错设成 inputoutput 都会抛 ora-06550 或返回空结果。
- 必须写
param.Direction = ParameterDirection.Output,仅设OracleDbType.RefCursor不够 - 参数名要和 PL/SQL 存储过程里
OUT参数名完全一致(区分大小写,除非用双引号定义) - 不要给 REF CURSOR 参数赋初值——
param.Value = null是安全的,但显式赋值会触发异常 - 如果存储过程有多个 REF CURSOR 输出,每个都得单独加
OracleParameter,顺序无关,靠名字匹配
DataReader 只能在 ExecuteReader() 后获取,不能用 ExecuteNonQuery()
很多人试过先 ExecuteNonQuery() 再想从参数里取游标,结果 param.Value 是 null——因为 Oracle 的 REF CURSOR 只在执行查询类命令时才真正绑定到结果集,ExecuteNonQuery() 不触发游标打开。
- 必须用
command.ExecuteReader(),哪怕你只关心输出参数里的游标 - 调用后立刻得到的
OracleDataReader就对应第一个 REF CURSOR;后续游标需通过reader.NextResult()切换 - 如果只声明了一个 REF CURSOR 输出,
NextResult()会返回false;多个时按参数声明顺序对应结果集顺序 - 别在
ExecuteReader()前读param.Value,此时它还是null
Oracle.ManagedDataAccess 和 ODP.NET Unmanaged 版本行为不一致
托管驱动(Oracle.ManagedDataAccess)默认支持 REF CURSOR 自动映射,而旧版非托管 ODP.NET(Oracle.DataAccess)需要额外配置或更严格类型声明,容易卡在“未找到数据类型”错误。
- 优先用
Oracle.ManagedDataAccess(NuGet 包名:Oracle.ManagedDataAccess),.NET Core / .NET 5+ 必选 - 若用非托管版,确保安装完整客户端,且
Oracle.DataAccess.dll架构(x86/x64)与应用进程一致 - 托管驱动下,
OracleDbType.RefCursor可直接用于参数,无需注册自定义类型 - 非托管版有时要求在连接字符串加
Unicode=True,否则中文列名可能乱码
DataReader 关闭后 REF CURSOR 在数据库端自动释放,但别手动 Close() 参数
Oracle 服务端在客户端关闭 OracleDataReader 时自动清理游标资源。试图手动调用 param.Value.Dispose() 或对 param.Value 做任何操作,基本都会抛 InvalidCastException 或 ObjectDisposedException。
-
OracleDataReader用using包裹即可,不用管参数对象 - 不要把
param.Value当作IDataReader强转——它只是个占位符,真实读取必须走ExecuteReader()返回的对象 - 如果存储过程中 REF CURSOR 来自
OPEN ... FOR动态 SQL,确保 SQL 语法正确,否则报错在ExecuteReader()时才暴露,不是参数绑定阶段 - 高并发下注意连接池和游标数限制:Oracle 默认
OPEN_CURSORS通常为 300,REF CURSOR 算一个打开游标
REF CURSOR 的麻烦不在 C# 侧怎么写,而在 PL/SQL 侧是否真打开了、有没有被提前关闭、以及驱动版本和连接配置是否暗中干扰了类型解析——出问题先查存储过程日志,再比对驱动文档里的 REF CURSOR 兼容表。

















