使用Dapper在Oracle中传递UDT调用存储过程时参数类型报错求助
解决Oracle UDT与C# Dapper调用存储过程的参数类型不匹配问题
问题根源
你在Oracle里定义的VList是嵌套表(Nested Table)类型,但C#代码里用了OracleCollectionType.PLSQLAssociativeArray——这对应Oracle的PL/SQL关联数组(Associative Array),两种集合类型完全不兼容;再加上参数名里的多余空格,直接触发了参数类型错误。
修复步骤(两种可选方案)
方案1:修改C#代码适配Oracle嵌套表
如果不想改动Oracle端的类型,按以下步骤调整C#代码:
修正参数名的空格问题
你的代码里paramUDT.ParameterName = "P_EmployeeIds "和paramRegular.ParameterName = "P_SEND_DEPTS "末尾多了空格,必须和存储过程里的参数名完全一致,改成:paramUDT.ParameterName = "P_EmployeeIds"; paramRegular.ParameterName = "P_SEND_DEPTS";正确配置嵌套表参数(结合Dapper)
嵌套表需要指定OracleDbType.Array和UDT类型名称,示例代码:public async Task<bool> SendMail(List<string> emIds, List<string> deptsIds) { using (var connection = new OracleConnection(connectionString)) { await connection.OpenAsync(); // 员工ID参数配置 var empParam = new OracleParameter { ParameterName = "P_EmployeeIds", OracleDbType = OracleDbType.Array, UdtTypeName = "VList", // 必须和Oracle中UDT名称完全一致(注意Oracle默认大小写) Value = emIds.ToArray() }; // 部门ID参数配置 var deptParam = new OracleParameter { ParameterName = "P_DeptsIds", OracleDbType = OracleDbType.Array, UdtTypeName = "VList", Value = deptsIds.ToArray() }; // 普通参数配置 var sendDeptParam = new OracleParameter { ParameterName = "P_SEND_DEPTS", OracleDbType = OracleDbType.Varchar2, Value = "T" }; // Dapper执行存储过程 await connection.ExecuteAsync("SEND_EMAIL_PROC", new { P_EmployeeIds = empParam, P_DeptsIds = deptParam, P_SEND_DEPTS = sendDeptParam }, commandType: CommandType.StoredProcedure); return true; } }可选:解决UDT序列化问题
如果运行时提示UDT无法识别,可在配置文件(app.config/web.config)添加映射:<oracle.dataaccess.client> <settings> <add name="VList" value="你的命名空间.VList, 你的程序集名称"/> </settings> </oracle.dataaccess.client>或在代码中注册:
OracleUdtMapping.RegisterMapping("VList", typeof(List<string>));
方案2:修改Oracle存储过程为关联数组类型(更简便)
如果业务允许修改Oracle端,把嵌套表改成PL/SQL关联数组,就能直接适配C#里的PLSQLAssociativeArray配置:
修改UDT定义:
CREATE OR REPLACE TYPE VList AS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;只需要修正C#代码里参数名的空格问题,即可正常调用。
关键注意事项
- Oracle的UDT名称默认是大写的,C#里指定
UdtTypeName时必须和数据库中的名称完全匹配(若创建时用了小写,需加双引号)。 - 用Dapper传递UDT参数时,直接将
OracleParameter作为参数值传入即可,Dapper会自动处理。
内容的提问来源于stack exchange,提问作者HarryHeart
相关产品推荐
相关产品推荐

