You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dapper:不修改原有数据库表,如何返回含嵌套对象的对象列表?

错误原因分析

问题出在Dapper的自动映射逻辑上:查询结果中testobject表的detailId列是int类型,但TestObject类中同名的detailId属性是ObjectDetail类型,Dapper会尝试将int值强制转换为ObjectDetail,最终触发类型转换异常。

无需修改数据库表的解决方案

方案一:用[Ignore]特性跳过属性自动映射

在TestObject的detailId属性上添加Dapper的[Ignore]特性,阻止Dapper自动映射该属性,转而通过多映射回调手动赋值:

using Dapper;

public class TestObject
{
    public int objectId { get; set; }
    public string name { get; set; }
    [Ignore] // 让Dapper跳过该属性的自动映射
    public ObjectDetail detailId { get; set; }
}

public class ObjectDetail
{
    public int detailId { get; set; }
    public string owner { get; set; }
    public string description { get; set; }       
}

原有SQL和查询代码无需修改,Dapper会自动跳过TestObject.detailId的映射,仅通过回调函数将ObjectDetail实例赋值给该属性。

方案二:修改SQL列名避免冲突

调整SQL语句,将testobject表的detailId列重命名,避免与objectdetail表的detailId列重名,同时保持多映射的分割逻辑:

string sql = $"select ob.objectId, ob.name, ob.detailId as detailForeignKey, de.* " +
             $"from dbo.testobject ob " +
             $"left join dbo.objectdetail de " +
             $"on ob.detailId = de.detailId ";

using (IDbConnection connection)
{
    var selected = connection.Query<TestObject, ObjectDetail, TestObject>(sql,
        (test, detail) => { test.detailId = detail; return test; },
        splitOn: "detailId");
}

如果不需要保留外键值,TestObject类可以不做修改(Dapper会自动忽略无对应属性的列);若需要保留外键值,可在TestObject中添加对应属性:

public class TestObject
{
    public int objectId { get; set; }
    public string name { get; set; }
    public int detailForeignKey { get; set; } // 接收重命名后的外键列值
    public ObjectDetail detailId { get; set; }
}

内容的提问来源于stack exchange,提问作者kenLeeDep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:02:04