存储过程名必须带schema前缀,否则报ora-06576;输入参数须显式指定oracledbtype,不可依赖dapper自动推断;ref cursor输出必须用dapper.oracle的oracledynamicparameters,原生dynamicparameters不支持。

存储过程名必须带Schema前缀,否则ORA-06576报错
Oracle不认裸过程名,Query("get_user", ...) 会直接失败,错误是 ORA-06576: not a valid function or procedure name。根本原因是Oracle要求全限定名,哪怕在当前Schema下也得写成 "SCHEMA_NAME.GET_USER" 或 "PKG_USER.GET_USER"。
常见踩坑点:
- 开发库用
HR.GET_EMP,上线库换成了APP_OWNER.GET_EMP,忘了改代码 - 用了同义词但没确认其指向的Schema,调用时仍按旧名写
- 大小写敏感:数据库里建的是
"GetUser"(带双引号),代码里传"getuser"就匹配不上
输入参数必须显式指定OracleDbType,不能靠Dapper自动推断
Dapper默认按SQL Server语义猜类型,Oracle不买账。比如传 new { id = 123 },ODP.NET可能把 int 当成 VARCHAR2 绑定,触发 ORA-06502。
正确做法是用 DynamicParameters 并逐个声明类型:
-
NUMBER字段 → 用OracleDbType.Int32或OracleDbType.Decimal(精度敏感时选后者) -
VARCHAR2输入 →OracleDbType.Varchar2,值可直接传string -
DATE→OracleDbType.Date,.NET的DateTime能直传 - 别加
@前缀,Oracle参数名就是"p_id",不是"@p_id"
输出参数不设size或dbType就崩,ORA-06502几乎必现
VARCHAR2 输出参数如果只写 p.Add("msg", direction: ParameterDirection.Output),ODP.NET会按size=0处理,直接抛 ORA-06502。NUMBER类输出若没指定 OracleDbType,也可能被当字符串解析失败。
关键配置项:
-
VARCHAR2输出必须带size:例如p.Add("p_msg", dbType: OracleDbType.Varchar2, size: 200, direction: ParameterDirection.Output) -
NUMBER输出别用Int32,优先用OracleDbType.Decimal,避免精度丢失 -
REF CURSOR输出不能用原生DynamicParameters,必须换OracleDynamicParameters(来自Dapper.Oracle包) - 调用后取值用
p.Get<string>("p_msg")</string>,不是p.Get("p_msg")
REF CURSOR必须用Dapper.Oracle,原生Dapper完全不支持
原生 DynamicParameters 加 OracleDbType.RefCursor 会直接抛异常:“无法将OracleRefCursor转换为IEnumerable
必须走这条路径:
- NuGet安装
Dapper.Oracle(不是Dapper本体) - 用
OracleDynamicParameters替代DynamicParameters - 参数声明写成
p.Add("p_cursor", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output) - 执行用
Query<t>()</t>,不是Execute();语句名仍是全限定存储过程名,如"PKG_ORDER.GET_ITEMS"
真正容易被忽略的是:即使你装了 Dapper.Oracle,如果没引用它的命名空间、或者仍用 new DynamicParameters(),游标照样拿不到数据——类型擦除发生在构造那一刻,不是执行时。











