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

来源:这里教程网 时间:2026-02-21 17:35:31 作者:

用Dapper做一对一映射,核心就三点:写对SQL、选对

splitOn
列、写好组装委托。它不自动推断关系,但控制清晰、性能高,适合明确知道数据结构的场景。

SQL要包含两个表的字段,并注意列名不冲突

必须把主表和关联表的所有需要字段都查出来,推荐用表别名避免同名列覆盖(比如两个表都有

Id
):

示例SQL:

SELECT p.Id AS PostId, p.Content, u.Id AS UserId, u.Name AS UserName<br>  FROM Posts p<br>  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<Post, User, Post>(sql,<br>  (post, user) => {<br>    post.Owner = user;<br>    return post;<br>  },<br>  splitOn: "UserId"<br>);

关键细节:

post
user
都是Dapper根据
splitOn
自动创建的实例
LEFT JOIN
user
可能是
null
,建议在赋值前判断:
post.Owner = user ?? new User();
或保留null并用空合并操作符访问:
post.Owner?.Name
返回类型写
Post
,表示最终列表是
IEnumerable<post></post>

实体类得有可写属性,且类型匹配

比如

Post
类里要有
public User Owner { get; set; }
,不能是只读属性或私有字段。Dapper只映射public set属性,且不支持自动构造嵌套对象(不会调用
new User()
)。

如果

Owner
属性类型和SQL中映射的
User
不一致(比如写成了
object
),运行时会抛异常,不是静默失败。

基本上就这些。不复杂但容易忽略别名和splitOn的对应关系。

相关推荐