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
相关产品推荐
相关产品推荐

