oracle参数需加冒号前缀,游标须用oracledbtype.refcursor显式声明,长字符串超4000字节要设为clob,连接字符串必须含unicode=true防乱码。
oracle参数名必须带冒号前缀,dapper不自动补
oracle驱动(比如 oracle.manageddataaccess)要求所有参数名显式以 : 开头,而 dapper 默认生成的参数名是无前缀的(如 @id)。直接写 where id = @id 会报错 ora-01036: illegal variable name/number。
解决办法只有两个:手动改 SQL 字符串,或用 IDbCommand 预处理。推荐前者,简单直接:
- 把
WHERE name = @name改成WHERE name = :name - 传参时仍用 C# 对象或匿名类型,Dapper 能识别字段名匹配
:name - 注意:不能混用,比如
:name和@name同时出现会失败
示例:
conn.Query<user>("SELECT * FROM users WHERE dept_id = :deptId", new { deptId = 10 });</user>
Oracle游标必须用OracleDbType.RefCursor显式声明
Dapper 本身不解析 PL/SQL 块,也不识别 OUT SYS_REFCURSOR。如果你调用存储过程返回游标,必须自己构造 OracleParameter 并设为 OracleDbType.RefCursor,再交给 Dapper 执行。
常见错误是直接写 new { result = new OracleParameter(...) } —— Dapper 会忽略这种复杂参数,导致游标为空或类型不匹配。
- 先创建
OracleParameter,Direction = ParameterDirection.Output,OracleDbType = OracleDbType.RefCursor - 用
conn.Execute()或conn.Query()时,把参数放进DynamicParameters,别用匿名对象 - 执行后从
DynamicParameters中取回游标值,再用Query<t>()</t>解析
示例:
var p = new DynamicParameters();<br>p.Add("p_cursor", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output);<br>conn.Execute("BEGIN get_users_by_dept(:p_cursor, :dept_id); END;", p, new { dept_id = 20 });<br>var users = p.Get<sqlmapper.icustomquery>(“p_cursor”).Query<user>(conn);</user></sqlmapper.icustomquery>
Oracle字符串长度超4000字节要主动设OracleDbType.Clob
Oracle 的 VARCHAR2 最大 4000 字节(字符集影响实际字符数),但 .NET 的 string 没限制。Dapper 默认把 string 映射为 VARCHAR2,插入长文本时会静默截断或抛 ORA-01461 错误。
- 明确知道字段是
CLOB的,传参时必须用OracleParameter指定OracleDbType.Clob - 不能靠 Dapper 自动推断 —— 它没 Oracle 类型上下文
- 查询时 CLOB 字段能正常映射为
string,无需额外处理
示例:
var p = new DynamicParameters();<br>p.Add("content", "很长很长...", OracleDbType.Clob, ParameterDirection.Input);<br>conn.Execute("INSERT INTO docs(content) VALUES (:content)", p);
连接字符串里Unicode=true必须开,否则中文乱码
Oracle.ManagedDataAccess 默认用数据库字符集解码响应,但 .NET 字符串是 UTF-16。如果连接字符串没加 Unicode=true,中文字段查出来可能是乱码或空值,尤其在 AL32UTF8 库上更明显。
- 连接字符串末尾加上
;Unicode=True(注意分号) - 不要依赖
NLS_LANG环境变量,它不可靠且无法被 Dapper 控制 - 这个设置只影响字符传输编码,不影响日期、数字等其他类型
示例连接字符串:
Data Source=ORCL;User Id=scott;Password=tiger;Unicode=True;
Oracle 和 Dapper 的配合不是即插即用的,关键点全在驱动层约定上:参数前缀、游标类型、LOB 显式声明、字符编码开关——漏掉任何一个,都会在运行时才暴露,而且错误信息往往不指向根本原因。











