必须显式传 CommandType.StoredProcedure,否则 Dapper 按普通 SQL 解析导致“对象名无效”等错误;调用存储过程需指定 commandType,参数用 DynamicParameters,输出值须在原连接关闭前读取。

必须显式传 CommandType.StoredProcedure,否则 Dapper 一律当普通 SQL 字符串解析,报“对象名无效”或“找不到存储过程”。
不加 commandType: CommandType.StoredProcedure 就会报错
Dapper 的 Query、Execute、QuerySingle 等方法底层只认字符串内容,不会自动识别你写的 "usp_GetUser" 是存储过程名还是表名。SQL Server 收到 CommandType.Text 类型的命令后,直接按 T-SQL 语法解析,自然找不到对象。
- 错误现象:
Invalid object name 'usp_GetUser'或Could not find stored procedure - 正确写法:
conn.Query<user>("usp_GetUser", commandType: CommandType.StoredProcedure)</user> - 别写
"EXEC usp_GetUser"、"usp_GetUser()"或带分号的字符串——Dapper 不需要也不接受这些语法 - SQL Server 默认按当前用户默认 Schema 查找,一般不用写
dbo.usp_GetUser,除非存在同名不同 Schema 的冲突
带参数时用 DynamicParameters,别拼字符串
输入参数可用匿名对象,但只要涉及 OUTPUT、RETURN、REF CURSOR 或 Oracle 类型,就必须用 DynamicParameters 显式控制类型和方向。
- SQL Server 示例:
param.Add("@id", 123, DbType.Int32, ParameterDirection.Input) - Oracle 必须指定
DbType和direction,比如VARCHAR2输出要写DbType.AnsiString+size: 4000,否则可能抛ORA-06502 -
REF CURSOR在 Oracle 中必须配DbType.Object+OracleDbType.RefCursor+ParameterDirection.Output - 别依赖
typeof(string)自动映射——Oracle 驱动要求精确匹配DbType
想拿 OUTPUT 或 RETURN 值?别用 QuerySingle<int>
QuerySingle<T> 只读结果集第一行第一列;Execute 不返回任何值;ExecuteScalar 只取标量。它们都拿不到存储过程的输出参数或返回码。
- 正确做法:执行后调用
param.Get<int>("@ReturnCode")或param.Get<string>("@Message") - 若同时有结果集 + 输出参数,用
QueryMultiple,再分别调grid.Read<User>()和grid.ReadFirst(),但输出参数仍得从DynamicParameters里读 - 异步场景下,
SqlConnection生命周期必须覆盖整个 await + 参数读取过程;using提前释放连接会导致InvalidOperationException或null值
无参存储过程最简单,但也最容易漏掉 commandType
不需要传 null,也不用构造空 new { },直接传存储过程名即可。
- 查询类:
conn.Query<User>("GetActiveUsers", commandType: CommandType.StoredProcedure) - 执行类:
conn.Execute("UpdateCache", commandType: CommandType.StoredProcedure) - 常见疏忽:复制了带参示例代码,删掉参数却忘了删
commandType—— 这个参数不能省 - 连接未打开时,Dapper 会自动打开,但建议明确控制生命周期,尤其在事务或长连接场景中
最易被忽略的是:所有输出参数的读取动作,必须发生在原 SqlConnection 未关闭之前;换连接、跨 await、或在 using 块外访问 DynamicParameters.Value,值就丢了。


















