Dapper的splitOn支持用英文逗号分隔多个列名,用于多级嵌套映射;如查询返回OrderId,OrderNo,CustomerId,CustomerName,AddressId,Street,需写splitOn:"CustomerId,AddressId"以正确分割Order、Customer、Address三个对象。

Dapper 的 splitOn 参数支持多个列名,用英文逗号分隔即可,比如 splitOn: "OrderId,ProductId"。这不是“多次 splitOn”,而是一次指定多个分割点,用于多级嵌套映射(如一查三:Order → Customer → Address)或一对多场景中区分不同实体的起始字段。
什么时候需要多个 splitOn
当 SQL 查询返回三张及以上表的扁平化结果(例如 JOIN 了 Order、Customer、Address),且各实体主键列名不统一(比如不是都叫 Id)时,Dapper 需要明确知道每个新对象从哪一列开始。这时就靠多个列名告诉它:“这里切一刀,开始映射下一个对象”。
- 第一个对象(如
Order)取splitOn之前的所有列 - 第二个对象(如
Customer)从第一个splitOn列(如CustomerId)开始,到下一个splitOn列前为止 - 第三个对象(如
Address)从第二个splitOn列(如AddressId)开始,取剩余所有列
正确写法示例
假设查询返回:OrderId, OrderNo, CustomerId, CustomerName, AddressId, Street
你想映射为 Order → Customer → Address:
var result = conn.Query( sql, (order, customer, address) => { order.Customer = customer; customer.Address = address; return order; }, splitOn: "CustomerId,AddressId" // 关键:两个分割点 );
常见误区提醒
-
不要重复写多个 splitOn 参数:Dapper 只接受一个
splitOn:参数,值是字符串,不是数组或多个键值对 -
顺序必须和泛型参数顺序一致:泛型是
,那splitOn中第一个列对应T2起始,第二个列对应T3起始 - 列名必须真实存在于 SELECT 结果中,且大小写需匹配(取决于数据库配置,建议显式别名)
- 如果某关联记录为空(如 Customer 为 NULL),Dapper 仍能正常映射,但你要在委托函数里判空,避免 NullReferenceException
一对多场景下不直接靠 splitOn 解决
splitOn 本身只处理“一对一”或“线性嵌套”,不能自动展开集合(如一个 Order 对应多个 OrderItem)。要做一对多,得配合 Dictionary 手动归组,或者改用 QueryMultiple 分步查——这时候 splitOn 就只用一次,甚至不用。
基本上就这些。










