Oracle存储过程输出参数必须显式指定DbType和Direction,DynamicParameters需手动设置,否则报ORA-06502或返回null;REF CURSOR须用DbType.Object+OracleDbType.RefCursor+Output;VARCHAR2输出必设size;NUMBER对应DbType.Decimal而非Int32。
Oracle存储过程中输出参数必须显式指定 DbType 和 Direction
dapper 本身不自动推断 oracle 的输出参数类型,dynamicparameters 必须手动设置 dbtype 和 direction,否则会报 ora-06502: pl/sql: numeric or value error 或直接返回 null。oracle 驱动(如 oracle.manageddataaccess)对参数绑定比 sql server 更严格。
实操建议:
- 所有
out或in out参数都用new OracleParameter(...)显式构造,或在DynamicParameters.Add()中传入dbType和direction - 不要依赖 Dapper 自动映射——比如传
typeof(string)不等于DbType.AnsiString,Oracle 要求精确匹配 - 常见输出类型对应关系:
VARCHAR2 → DbType.AnsiString,NUMBER → DbType.Decimal,DATE → DbType.DateTime,REF CURSOR → DbType.Object
REF CURSOR 输出必须用 OracleDbType.RefCursor 且绑定为 ParameterDirection.Output
Oracle 存储过程返回结果集时,通常用 OUT SYS_REFCURSOR。Dapper 无法直接解析裸 OracleParameter 的游标,必须让 DynamicParameters 正确识别并交由驱动处理。
实操建议:
- 添加参数时,
DbType设为DbType.Object,OracleDbType设为OracleDbType.RefCursor(需引用Oracle.ManagedDataAccess.Client) -
Direction必须是ParameterDirection.Output,不能是InputOutput - 调用后,用
grid.Read()(如果用QueryMultiple)或grid.Read<t>()</t>拉取结果,不能直接Query<t>()</t> - 示例关键行:
params.Add("cur_result", dbType: DbType.Object, direction: ParameterDirection.Output, oracleDbType: OracleDbType.RefCursor)
DynamicParameters.Add() 的 size 参数对 VARCHAR2 输出很关键
Oracle 要求 VARCHAR2 类型的输出参数必须预设 Size,否则可能截断或抛出 ORA-06502。Dapper 的 DynamicParameters 默认 size 为 0,而 Oracle 驱动拒绝 size 为 0 的输出字符串参数。
实操建议:
- 所有
DbType.AnsiString输出参数,必须显式传size,例如size: 4000 - 避免用
int.MaxValue或极大值——某些 Oracle 驱动版本会因此报ORA-01008: not all variables bound - 如果不确定长度,宁可设大一点(如 32767),但要确认数据库字符集和客户端支持(AL32UTF8 下 32767 字节 ≈ 8191 个中文)
- 错误写法:
params.Add("out_msg", dbType: DbType.AnsiString, direction: ParameterDirection.Output)(缺 size)
连接字符串和 Oracle 版本影响 ParameterDirection behavior
Oracle 12c 及以后默认启用 UseUnicode=true,但老版本驱动或未配置时,DbType.AnsiString 可能被当成 CHAR 处理,导致空格填充、比较异常;同时,某些低版本驱动(如 19.3 以前)对 ParameterDirection.ReturnValue 支持不完整,应统一用 Output。
实操建议:
- 连接字符串中显式加
Unicode=True,避免隐式编码转换 - 不用
ReturnValue类型参数——Oracle 存储过程没有真正意义上的“return value”,所谓函数返回值也得走OUT参数 - 测试阶段打开 Oracle 客户端日志(
TraceLevel=7)可快速定位参数绑定失败的具体字段 - 若用 Oracle.ManagedDataAccess v21+,注意
OracleParameter.Size对CLOB类型无效,CLOB 输出应改用OracleDbType.Clob+direction: Output
最易被忽略的是:即使存储过程定义了 OUT p_code NUMBER,你也得在 C# 里写 DbType.Decimal 而不是 DbType.Int32,Oracle NUMBER 没有整数子类型,驱动不会帮你缩窄。


















