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

使用C#调用PostgreSQL存储过程时出现参数类型不匹配错误

问题描述

我尝试通过带表值参数的存储过程进行数据更新/插入操作,相关代码和定义如下:

C# 实体类定义

public class classA
{
    public DateTime Param1 { get; set; }
    public string Param2 { get; set; }
    public string Param3 { get; set; }
    public int Param4 { get; set; }
    public int Param5 { get; set; }
    public decimal Param6 { get; set; }
    public int Param7 { get; set; }
    public string Param8 { get; set; }
    public bool Param9 { get; set; }
    public bool Param10 { get; set; }
    public bool Param11 { get; set; }
    public string Param12 { get; set; }
    public string Param13 { get; set; }
    public string Param14 { get; set; }
    public string Param15 { get; set; }
    public string Param16 { get; set; }
    public string Param17 { get; set; }
    public int Param18 { get; set; }
    public int Param19 { get; set; }
    public int Param20 { get; set; }
    public int Param21 { get; set; }
    public int Param22 { get; set; }
    public string Param23 { get; set; }
    public string Param24 { get; set; }
    public string Param25 { get; set; }
    public string Param26 { get; set; }
    public string Param27 { get; set; }
    public string Param28 { get; set; }
    public string Param29 { get; set; }
    public string Param30 { get; set; }
    public string Param31 { get; set; }
    public string Param32 { get; set; }
    public string Param33 { get; set; }
    public string Param34 { get; set; }
}

C# 调用存储过程的方法

public static void ExecuteStoredProcedureWithSingleTableTypeParameter<T>(string connectionString, string storedProcedureName, List<T> parameters)
{
    using (var connection = new NpgsqlConnection(connectionString))
    {
        connection.Open();

        using (var command = new NpgsqlCommand(storedProcedureName, connection))
        {
            command.CommandType = CommandType.StoredProcedure;

            // 假设存储过程中的参数名为"p_data"
            var parameter = new NpgsqlParameter
            {
                ParameterName = "p_data",
                NpgsqlDbType = NpgsqlDbType.Jsonb,
                Direction = ParameterDirection.Input,
                Value = JsonConvert.SerializeObject(parameters, new JsonSerializerSettings
                {
                    ContractResolver = new LowercaseContractResolver(),
                    Formatting = Formatting.None // 可按需调整格式化方式
                })
            };

            command.Parameters.Add(parameter);

            command.ExecuteNonQuery();
        }
    }
}

PostgreSQL 自定义表类型

CREATE TYPE Test.TableType1 AS (
   Param1 Date,
   Param2 varchar(50),
   Param3 varchar(30),
   Param4 int,
   Param5 int,
   Param6 decimal(3,1),
   Param7 int,
   Param8 varchar(255),
   Param9 boolean,
   Param10 boolean,
   Param11 boolean,
   Param12 varchar(50),
   Param13 varchar(30),
   Param14 varchar(150),
   Param15 varchar(500),
   Param16 varchar(255),
   Param17 varchar(500),
   Param18 int,
   Param19 int,
   Param20 int,
   Param21 int,
   Param22 int,
   Param23 varchar(50),
   Param24 varchar(30),
   Param25 varchar(255),
   Param26 varchar(50),
   Param27 varchar(30),
   Param28 varchar(255),
   Param29 varchar(255),
   Param30 varchar(10),
   Param31 varchar(10),
   Param32 varchar(30),
   Param33 varchar(100),
   Param34 varchar(255)
);

PostgreSQL 存储过程定义

CREATE OR REPLACE PROCEDURE Test.SP1(
    p_data Test.TableType1
)
LANGUAGE plpgsql
AS $$
BEGIN
    -- 执行语句
END;
$$;

调用方式

DBRepository.ExecuteStoredProcedureWithSingleTableTypeParameter(connectionString, "test.sp1", listingData);

错误提示

提示:没有匹配给定名称和参数类型的过程,可能需要添加显式类型转换。
42883: procedure test.sp1(p_data => jsonb) does not exist
POSITION: 6

我是PostgreSQL新手,请问该如何解决这个问题?


解决方案

错误核心原因是:C#代码传递的是JSONB类型参数,但存储过程定义的参数类型是自定义的Test.TableType1,类型不匹配导致PostgreSQL找不到对应存储过程。以下是两种可行解决思路:

思路一:修改存储过程,接收JSONB参数并转换为自定义表类型

无需改动C#代码,仅调整PostgreSQL端逻辑:

  1. 将存储过程参数类型改为jsonb
  2. 在存储过程内部将JSONB数据转换为Test.TableType1类型的记录(单条或多条)

示例修改后的存储过程:

CREATE OR REPLACE PROCEDURE Test.SP1(
    p_data jsonb
)
LANGUAGE plpgsql
AS $$
DECLARE
    v_record Test.TableType1;
    -- 若处理多条数据,可定义数组变量
    -- v_records Test.TableType1[];
BEGIN
    -- 单条数据转换
    v_record := jsonb_populate_record(null::Test.TableType1, p_data);
    
    -- 多条数据转换(将JSON数组转为记录数组)
    -- v_records := array(select jsonb_populate_record(null::Test.TableType1, elem) from jsonb_array_elements(p_data) elem);
    
    -- 此处编写插入/更新逻辑,例如:
    -- INSERT INTO your_target_table SELECT (v_record).*;
END;
$$;

思路二:修改C#代码,直接传递PostgreSQL自定义表类型参数

调整C#代码,让Npgsql直接传递Test.TableType1类型参数,无需转JSON:

  1. 确保classA属性名与自定义表类型字段名完全匹配(PostgreSQL区分大小写)
  2. 修改参数的NpgsqlDbType为Composite并指定类型名称

修改后的C#方法:

public static void ExecuteStoredProcedureWithSingleTableTypeParameter<T>(string connectionString, string storedProcedureName, List<T> parameters)
{
    using (var connection = new NpgsqlConnection(connectionString))
    {
        connection.Open();
        // 提前映射实体类与数据库复合类型(可放在程序启动时执行一次)
        NpgsqlConnection.GlobalTypeMapper.MapComposite<classA>("Test.TableType1");

        using (var command = new NpgsqlCommand(storedProcedureName, connection))
        {
            command.CommandType = CommandType.StoredProcedure;

            var parameter = new NpgsqlParameter
            {
                ParameterName = "p_data",
                // 配置复合类型参数
                NpgsqlDbType = NpgsqlDbType.Composite,
                DataTypeName = "Test.TableType1",
                Direction = ParameterDirection.Input,
                // 单条数据传第一条,多条数据则传数组并修改存储过程参数为Test.TableType1[]
                Value = parameters.FirstOrDefault()
            };

            command.Parameters.Add(parameter);
            command.ExecuteNonQuery();
        }
    }
}

若需传递多条数据,同步修改存储过程参数为数组类型:

CREATE OR REPLACE PROCEDURE Test.SP1(
    p_data Test.TableType1[]
)
LANGUAGE plpgsql
AS $$
BEGIN
    -- 遍历数组处理每条记录
    FOREACH v_record IN ARRAY p_data LOOP
        -- 插入/更新逻辑示例
        -- INSERT INTO your_target_table SELECT (v_record).*;
    END LOOP;
END;
$$;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 09:19:56