如何在Dapper中实现实体的三级级联多映射关联?
如何在Dapper中实现三级实体的级联关联映射?
我明白你从EF6迁移到Dapper的处境——EF自动帮你处理了多级关联,但Dapper需要手动控制映射逻辑。你已经搞定了BENEFIT_POLIZZE(实体A)和BENEFIT_CLIENTI(实体B)的关联,现在要把实体B关联的GRUPPO_CLIENTE_MAIN(实体C)也映射进去,这完全可行,下面一步步来帮你实现:
首先,调整你的SQL查询,把实体C对应的表也join进来。假设实体C对应的表是GRUPPO_CLIENTI,关联字段是BENEFIT_CLIENTI.GRUPPO_CLIENTE_MAIN = GRUPPO_CLIENTI.ID_GRUPPO(你可以根据实际表结构调整),SQL需要改成这样:
SELECT Extent1.*, Extent2.*, Extent3.* FROM BENEFIT_POLIZZE Extent1 INNER JOIN BENEFIT_CLIENTI Extent2 ON Extent1.ID_CLIENTE = Extent2.ID_CLIENTE INNER JOIN GRUPPO_CLIENTI Extent3 ON Extent2.GRUPPO_CLIENTE_MAIN = Extent3.ID_GRUPPO WHERE Extent1.ID_POLIZZA_BENEFIT = @ID_POLIZZA_BENEFIT
注意:如果三个表有同名字段(比如都有
ID),一定要给字段加别名区分,避免映射混乱。
接下来,修改Dapper的Query方法,它支持多类型的映射,我们可以用Query<T1, T2, T3, TResult>的泛型重载,同时调整映射委托和splitOn参数:
var polizza = connection.Query<BENEFIT_POLIZZE, BENEFIT_CLIENTI, GRUPPO_CLIENTI, BENEFIT_POLIZZE>( @"SELECT Extent1.*, Extent2.*, Extent3.* FROM BENEFIT_POLIZZE Extent1 INNER JOIN BENEFIT_CLIENTI Extent2 ON Extent1.ID_CLIENTE = Extent2.ID_CLIENTE INNER JOIN GRUPPO_CLIENTI Extent3 ON Extent2.GRUPPO_CLIENTE_MAIN = Extent3.ID_GRUPPO WHERE Extent1.ID_POLIZZA_BENEFIT = @ID_POLIZZA_BENEFIT", (polizzaEntity, clienteEntity, gruppoEntity) => { // 先把最底层的实体C赋值给实体B的属性 clienteEntity.GRUPPO_CLIENTE_MAIN = gruppoEntity; // 再把实体B赋值给实体A的属性 polizzaEntity.BENEFIT_CLIENTI = clienteEntity; return polizzaEntity; }, param: new { ID_POLIZZA_BENEFIT = idPolizza }, splitOn: "ID_CLIENTE,ID_GRUPPO" // 按顺序指定每个实体的主键,拆分结果集 ).Distinct().Single();
关键要点解释:
- 泛型参数顺序:要和SQL查询返回的字段顺序对应——先
BENEFIT_POLIZZE的字段,然后BENEFIT_CLIENTI,最后GRUPPO_CLIENTI。 - splitOn参数:用逗号分隔每个实体的主键字段,告诉Dapper在哪里拆分结果集,把对应的字段映射到对应的实体。这里
ID_CLIENTE是BENEFIT_CLIENTI的主键,ID_GRUPPO是GRUPPO_CLIENTI的主键(根据你的实际表主键调整)。 - 映射委托:按从内到外的顺序赋值,先绑定最底层的关联,再往上传递。
额外注意事项:
- 如果查询结果可能出现重复的实体(比如join后产生多条重复数据),
Distinct()是必要的,但确保你的实体正确实现了Equals和GetHashCode,或者可以用DistinctBy(需要安装Dapper.Contrib扩展)来指定去重的字段。 - 如果你不确定查询结果是否唯一,
Single()会在结果为空或多条时抛出异常,可以根据场景换成SingleOrDefault()或FirstOrDefault()。
内容的提问来源于stack exchange,提问作者advapi
相关产品推荐
相关产品推荐

