You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Dapper在Oracle中传递UDT调用存储过程时参数类型报错求助

解决Oracle UDT与C# Dapper调用存储过程的参数类型不匹配问题

问题根源

你在Oracle里定义的VList是嵌套表(Nested Table)类型,但C#代码里用了OracleCollectionType.PLSQLAssociativeArray——这对应Oracle的PL/SQL关联数组(Associative Array),两种集合类型完全不兼容;再加上参数名里的多余空格,直接触发了参数类型错误。

修复步骤(两种可选方案)

方案1:修改C#代码适配Oracle嵌套表

如果不想改动Oracle端的类型,按以下步骤调整C#代码:

  1. 修正参数名的空格问题
    你的代码里paramUDT.ParameterName = "P_EmployeeIds "和paramRegular.ParameterName = "P_SEND_DEPTS "末尾多了空格,必须和存储过程里的参数名完全一致,改成:

    paramUDT.ParameterName = "P_EmployeeIds";
    paramRegular.ParameterName = "P_SEND_DEPTS";
    
  2. 正确配置嵌套表参数(结合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;
        }
    }
    
  3. 可选:解决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配置:

  1. 修改UDT定义:

    CREATE OR REPLACE TYPE VList AS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;
    
  2. 只需要修正C#代码里参数名的空格问题,即可正常调用。

关键注意事项

  • Oracle的UDT名称默认是大写的,C#里指定UdtTypeName时必须和数据库中的名称完全匹配(若创建时用了小写,需加双引号)。
  • 用Dapper传递UDT参数时,直接将OracleParameter作为参数值传入即可,Dapper会自动处理。

内容的提问来源于stack exchange,提问作者HarryHeart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:43:20