如何使用Dapper返回含Status、Client关联子对象的Job实体列表
Dapper 实现关联表查询填充导航属性方案
首先需要先修正你现有模型的一个问题,否则映射会失败:
JobModel的Id属性只有get访问器,是只读属性,Dapper无法给这个属性赋值,需要补充set访问器,可以用private set或者init限制外部修改权限,只要存在赋值入口就行。修正后代码:
public class JobModel { public int Id { get; set; } public string Description { get; set; } public StatusModel Status { get; set; } public ClientModel Client { get; set; } }
具体实现
Dapper原生自带多映射功能,不需要安装额外扩展包,直接用Query的多泛型重载就能实现关联对象填充,你写的联表SQL不需要改动,直接用就可以。
完整查询代码:
using var conn = new SqlConnection("你的数据库连接字符串"); var querySql = @"SELECT j.*, s.*, c.* FROM Job j INNER JOIN Status s ON j.StatusId = s.Id INNER JOIN Client c ON j.ClientId = c.Id;"; var result = conn.Query<JobModel, StatusModel, ClientModel, JobModel>( sql: querySql, map: (job, status, client) => { job.Status = status; job.Client = client; return job; }, splitOn: "Id,Id" ).ToList();
执行完成后result就是填充好Status和Client导航属性的JobModel列表。
关键参数说明
- 泛型参数顺序:必须和你SELECT语句返回的表字段顺序一致,你当前SQL是先返回Job字段、再返回Status字段、最后返回Client字段,所以前三个泛型依次对应这三个模型,最后一个泛型是最终返回的主实体类型,也就是
JobModel。 splitOn:用来标记Dapper切换映射实体的列名,因为三个表的主键都叫Id,所以按映射顺序,遇到第一个Id列(Status表主键)就开始映射StatusModel,遇到第二个Id列(Client表主键)就开始映射ClientModel,所以传"Id,Id"即可。如果后续关联表的主键名不是Id,替换成对应的列名就行。- 你的场景是Job单条记录对应单个Status、单个Client,联表结果不会出现重复的Job记录,不需要额外去重。如果是一对多场景(比如一个Job对应多条操作记录),用字典缓存已查询到的主实体去重就行。
内容的提问来源于stack exchange,提问作者Bazza Formez
相关产品推荐
相关产品推荐

