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

如何在C#中向PostgreSQL函数传递自定义类型数组

问题背景

我在PostgreSQL中定义了如下自定义复合类型及使用该类型的函数:

create type my_type as
(
    id bigint,
    value character varying(100)
);


create or replace function my_function (
    my_array my_type[])
    returns table (id bigint)
    language 'plpgsql'
as $BODY$
begin
return query
    select id from my_table as t
    where t.id in (
        select ar.id
        from unnest(my_array) as ar
    );
end;
$BODY$;

该函数在PostgreSQL中的调用方式如下:

select * from my_function(array[(1, 't')::my_type, (3, 'b')::my_type]);

我使用.NET Core 8.0和Npgsql 8.0.2进行测试,定义了对应的POCO类:

public class MyType
{
    public int Id {get; set;}
    public string Value {get; set;}
}

尝试通过以下代码调用函数时:

var dsBuilder = new NpgsqlDataSourceBuilder("my-connection-string");
dsBuilder.MapComposite<MyType>("my_type");
using var ds = dsBuilder.Build();
using var conn = ds.OpenConnection();

var cmd = new NpgsqlCommand("select * from my_function(@arr)", conn);
cmd.Parameters.AddWithValue(
     "arr",
     new MyType[] {
         new MyType(){ Id = 1, Value = "t" },
         new MyType(){ Id = 3, Value = "b" },
     }
);

运行时报错:Writing values of 'Program+MyType[]' is not supported for parameters having no NpgsqlDbType or DataTypeName,尝试传递IEnumerable<MyType>和List<MyType>类型参数也无效。想知道如何用NpgsqlDataSource在C#中正确调用该函数,是否必须改用低效的单个调用或JSON参数?

解决方法

你需要明确指定参数的PostgreSQL数据类型,因为Npgsql无法自动推断复合类型数组的类型信息,有两种可行方式:

方式一:指定参数的DataTypeName

在添加参数时,显式指定DataTypeName为my_type[](注意是数组类型名):

cmd.Parameters.AddWithValue(
    "arr",
    NpgsqlTypes.NpgsqlDbType.Array | NpgsqlTypes.NpgsqlDbType.Composite,
    new MyType[] {
        new MyType(){ Id = 1, Value = "t" },
        new MyType(){ Id = 3, Value = "b" },
    }
);

或者单独设置参数的DataTypeName属性:

var param = cmd.Parameters.AddWithValue(
    "arr",
    new MyType[] {
        new MyType(){ Id = 1, Value = "t" },
        new MyType(){ Id = 3, Value = "b" },
    }
);
param.DataTypeName = "my_type[]";

方式二:使用NpgsqlParameter构造函数指定类型

通过构造函数直接声明参数的数据库类型:

var param = new NpgsqlParameter("arr", NpgsqlDbType.Array | NpgsqlDbType.Composite)
{
    Value = new MyType[] {
        new MyType(){ Id = 1, Value = "t" },
        new MyType(){ Id = 3, Value = "b" },
    },
    DataTypeName = "my_type[]"
};
cmd.Parameters.Add(param);

这样Npgsql就能正确识别参数类型为自定义复合类型的数组,从而完成映射和调用。不需要改用单个调用或JSON参数,这种方式是原生支持的高效方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:27:26