Dapper映射嵌套复杂类型依赖MultiMapping和自定义TypeHandler:MultiMapping处理1对1/1对多及最多7层泛型组合,TypeHandler支持JSON字段自动序列化,CustomTypeMap应对继承场景,需手动处理列名冲突、NULL关联与N+1问题。
Dapper 映射嵌套复杂类型,核心靠 MultiMapping(多对象映射)和 自定义 TypeHandler 两类机制。它不自动递归解析三层以上对象,也不支持原生的“深度导航属性”映射(比如 Post.Owner.Address.City),但通过组合策略完全可以实现清晰、可控的深层结构。
这是最常用也最直接的方式,适用于两层或手动组装三层结构:
Query + splitOn 指定分割列(如 "UserId"),再在委托里赋值:(post, user) => { post.Owner = user; return post; }
Lookup 或 GroupBy 分组组装Query,最多支持 7 个泛型参数,splitOn 需传入逗号分隔字符串,如 "UserId,ProfileId",Dapper 会依序切分字段段当深层结构不适合拆成多表 JOIN(比如用户配置、订单明细项列表),推荐把嵌套部分存为 JSON 字段,再用自定义 TypeHandler 自动转换:
VARCHAR(MAX) 或原生 JSON(SQL Server 2016+ / MySQL 5.7+ / PostgreSQL)JsonTypeHandler 类,重写 Parse 和 SetValue,用 System.Text.Json 处理序列化SqlMapper.AddTypeHandler(new JsonTypeHandler());
public Address ShippingAddress { get; set; },Dapper 读写时自动处理当嵌套对象类型不固定(如基类 Notification 下有 EmailNotif、SmsNotif 子类),需靠 ITypeMap 实现运行时类型选择:
NotifType 值为 "Email")决定实例化哪个子类DefaultTypeMap 或实现 ITypeMap,在 GetMemberMaps 中注入逻辑SqlMapper.SetTypeMap(typeof(Notification), yourCustomMap) 全局生效User.PreferredNotif)就能返回具体子类型,而非空基类Dapper 不会像 EF Core 那样扫描导航属性并自动 JOIN。以下情况必须手动干预:
Id)→ 务必用 SQL 别名:p.Id as PostId, u.Id as UserId,并让 splitOn 对应别名post.Owne
r = user ?? null;
SELECT * 导致 splitOn 错位基本上就这些。Dapper 的嵌套映射不是“全自动”,但每一步都透明可控,写清楚 splitOn、写好映射委托、配对好 TypeHandler,深层结构也能很稳。