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

如何在Dapper中实现DTO自定义键类型到CLR类型的转换

解决Dapper/Dapper.Contrib对自定义键类型的自动转换问题

问题核心

你用自定义Key结构体作为DTO的主键字段,使用Dapper.Contrib的Insert<T>方法时抛出System.NotSupportedException——因为Dapper无法识别自定义的键类型。你希望不用手动转换参数,让Dapper自动处理自定义类型与数据库兼容CLR类型的转换。

解决方案

Dapper提供了**自定义类型处理器(TypeHandler)**机制,可以让你指定自定义类型如何与数据库类型互转。只需要实现SqlMapper.TypeHandler<T>接口并注册,Dapper就会自动用这个处理器处理对应类型的参数和结果。

步骤1:实现自定义类型处理器

针对你的Key结构体,创建类型处理器:

public class KeyTypeHandler : SqlMapper.TypeHandler<Key>
{
    // 从数据库读取值转换为Key类型
    public override Key Parse(object value)
    {
        return (int)value; // 利用已定义的隐式转换
    }

    // 将Key类型的值设置到数据库参数中
    public override void SetValue(IDbDataParameter parameter, Key value)
    {
        parameter.DbType = DbType.Int32;
        parameter.Value = (int)value; // 利用已定义的隐式转换
    }
}

步骤2:注册类型处理器

在程序初始化阶段(比如Main方法开头)注册处理器,让Dapper识别自定义类型:

SqlMapper.AddTypeHandler(new KeyTypeHandler());

步骤3:修改原有代码测试

现在你的代码可以直接使用Dapper.Contrib的Insert方法,无需手动转换参数:

static void Main(string[] args)
{
    // 注册自定义类型处理器
    SqlMapper.AddTypeHandler(new KeyTypeHandler());

    using (var connection = new SqlConnection("server=.;database=equus;integrated security=true;Encrypt=false"))
    {
        connection.Open();
        connection.Execute(@"If not exists (select name from sysobjects where name = 'User')
            CREATE TABLE dbo.[User](UserId int identity(1,1) primary key clustered, Name varchar(200))");
        var user = new User() { Name ="OSO", UserId = 1 };
        connection.Insert(user); // 现在可正常执行,无需手动转换
        connection.Close();
    }
}

public struct Key
{
    private readonly int _value;
    public Key(int value) { _value = value; }
    public static implicit operator Key(int value) { return new Key(value); }
    public static implicit operator int(Key key) { return key._value; }
}

public class User
{
    public Key UserId { get; set; }
    public string Name { get; set; }=string.Empty;
}

补充说明

  • 若需要支持可空的Key?类型,可额外实现NullableKeyTypeHandler,或者调整处理器为泛型兼容可空类型。
  • 该机制对Dapper.Contrib的Update<T>、Get<T>等方法同样生效,注册一次后全局可用。
  • 未来如果需要修改Key的底层类型(比如从int改为long),只需调整Key结构体的隐式转换逻辑和处理器中的DbType,无需改动业务代码,完全符合你抽象键类型的初衷。

内容的提问来源于stack exchange,提问作者Yván Ecarri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:49:50