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

Dapper不支持PostgreSQL单个复合类型?求原因及排查方向

Dapper处理PostgreSQL单个复合类型参数报错的原因与解决方案

问题背景

定义.NET记录Model,包含单个UserTimestamp类型属性A、B及数组属性C,其中UserTimestamp已通过DataSourceBuilder.MapComposite<UserTimestamp>("usertimestamp")完成与PostgreSQL复合类型usertimestamp的映射。使用Dapper操作时,单个复合类型属性抛出NotSupportedException,改为数组类型后操作恢复正常。

核心原因

  • Dapper的参数映射逻辑默认仅对基础类型、数组/集合等内置支持类型做自动处理,无法自动识别单个自定义复合类型实例与PostgreSQL复合类型的关联,因此不会触发Npgsql的复合类型序列化逻辑,导致报错。
  • 数组类型能正常工作,是因为Npgsql内置支持数组的映射处理,Dapper可直接将数组参数传递给Npgsql,触发对应的序列化流程。

解决方案

方案1:手动构建Npgsql参数

在执行Dapper命令时,为单个复合类型属性手动创建NpgsqlParameter,指定复合类型元数据:

var model = new Model(
    A: new UserTimestamp(1, DateTime.Now),
    B: new UserTimestamp(2, DateTime.Now),
    C: new[] { new UserTimestamp(3, DateTime.Now) }
);

var parameters = new DynamicParameters();
// 处理单个复合类型参数A
parameters.Add("A", model.A, DbType.Object, ParameterDirection.Input);
var npgsqlParamA = (NpgsqlParameter)parameters.GetDbParameter("A");
npgsqlParamA.NpgsqlDbType = NpgsqlDbType.Composite;
npgsqlParamA.TypeName = "usertimestamp";

// 同理处理参数B
parameters.Add("B", model.B, DbType.Object, ParameterDirection.Input);
var npgsqlParamB = (NpgsqlParameter)parameters.GetDbParameter("B");
npgsqlParamB.NpgsqlDbType = NpgsqlDbType.Composite;
npgsqlParamB.TypeName = "usertimestamp";

// 数组参数C直接正常添加
parameters.Add("C", model.C);

// 执行Dapper命令
connection.Execute("INSERT INTO your_table (a, b, c) VALUES (@A, @B, @C)", parameters);

方案2:自定义Dapper类型处理器

实现SqlMapper.TypeHandler<UserTimestamp>,让Dapper自动处理单个复合类型实例的参数映射:

public class UserTimestampTypeHandler : SqlMapper.TypeHandler<UserTimestamp>
{
    public override void SetValue(IDbDataParameter parameter, UserTimestamp value)
    {
        var npgsqlParam = (NpgsqlParameter)parameter;
        npgsqlParam.NpgsqlDbType = NpgsqlDbType.Composite;
        npgsqlParam.TypeName = "usertimestamp";
        npgsqlParam.Value = value;
    }

    public override UserTimestamp Parse(object value)
    {
        // 若需要支持查询结果的反序列化,在此实现逻辑
        return (UserTimestamp)value;
    }
}

在应用启动时注册该类型处理器:

SqlMapper.AddTypeHandler(new UserTimestampTypeHandler());

注册后,直接使用Model原结构执行Dapper操作即可,无需手动处理参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:05:24