跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Dapper如何处理一对一关系 Dapper一对一查询映射教程

Dapper一对一映射需写对SQL、选准splitOn列、写好组装委托;SQL须用别名避免同名列冲突,splitOn填关联对象首列名(如"UserId"),委托中手动赋值并处理null。 用Dapper做一对一映射,核心就三点:写对SQL、选对
splitOn
列、写好组装委托。它不自动推断关系,但控制清晰、性能高,适合明确知道数据结构的场景。 SQL要包含两个表的字段,并注意列名不冲突 必须把主表和关联表的所有需要字段都查出来,推荐用表别名避免同名列覆盖(比如两个表都有
Id
): 示例SQL:
SELECT p.Id AS PostId, p.Content, u.Id AS UserId, u.Name AS UserName
FROM Posts p
LEFT JOIN Users u ON u.Id = p.OwnerId
这样能确保Dapper按列顺序准确切分数据段。如果不用别名,且两表都有
Id
,Dapper可能误判分割点。 splitOn参数指定关联对象的起始列
splitOn
不是写外键名,而是写“第二个对象字段在结果集里第一次出现的列名”。上例中
User
对象从
UserId
列开始,所以设为
"UserId"
: 如果SQL里写的是
u.Id
且没别名,那
splitOn
填
"Id"
(但容易和
p.Id
混淆) 如果用了
u.Id AS UserId
,就填
"UserId"
——更安全、更明确 大小写敏感,必须和SQL中AS后的名称完全一致 用委托函数把子对象挂到父对象属性上 Query方法返回的是主对象类型,嵌套对象靠你自己在委托里赋值:
var posts = connection.Query(sql,
(post, user) => {
post.Owner = user;
return post;
},
splitOn: "UserId"
);
关键细节:
post
和
user
都是Dapper根据
splitOn
自动创建的实例
LEFT JOIN
时
user
可能是
null
,建议在赋值前判断:
post.Owner = user ?? new User();
或保留null并用空合并操作符访问:
post.Owner?.Name
返回类型写
Post
,表示最终列表是
IEnumerable
实体类得有可写属性,且类型匹配 比如
Post
类里要有
public User Owner { get; set; }
,不能是只读属性或私有字段。Dapper只映射public set属性,且不支持自动构造嵌套对象(不会调用
new User()
)。 如果
Owner
属性类型和SQL中映射的
User
不一致(比如写成了
object
),运行时会抛异常,不是静默失败。 基本上就这些。不复杂但容易忽略别名和splitOn的对应关系。

相关文章