Dapper使用splitOn映射复杂对象时触发空引用异常如何排查
问题原因
空引用异常由核心配置错误触发,另外还有两处逻辑问题会导致后续运行异常:
splitOn参数格式错误:逗号后带了多余空格,低版本Dapper不会自动裁剪分割列名的前后空白,会尝试匹配名为custom_width(带前导空格)的列,匹配失败时没有友好报错,直接触发空引用。- 分割映射顺序错误:Dapper多映射的分割逻辑是从查询结果列的最右端往左匹配splitOn列表里的列,你当前的列顺序下,lambda的第二个输入参数拿到的是
custom_height的值,第三个参数拿到的是custom_width的值,原代码宽高赋值写反了。 - 参数传值笔误:
QueryAsync第三个参数是SQL参数对象,和SQL语句里的表别名p没有任何关系,如果这里传入的p不是提前定义好、包含boardId和userId属性的对象,即使修复映射问题也会抛出参数缺失异常。
修复后代码
const string panelsSql = @" SELECT p.panel_id, p.board_id, p.type_id, p.size_id, p.created_on, p.updated_on, p.custom_height, p.custom_width FROM CAT.panels p JOIN CAT.boards b ON b.board_id = p.board_id WHERE p.board_id = @boardId AND b.user_id = @userId;"; return await conn.Connection.QueryAsync<Panel, int, int, Panel>( panelsSql, (panel, height, width) => { panel.CustomSize = new Common.Objects.CustomPanelSize { Width = width, Height = height }; return panel; }, new { boardId, userId }, // 如果提前定义了包含这两个属性的参数对象p,也可以替换成p splitOn: "custom_height,custom_width" // 去掉逗号后的多余空格 ).ConfigureAwait(false);
补充适配
如果数据库中custom_height/custom_width字段允许为NULL,需要把泛型里的int改为可空类型int?,增加空值判断避免转换异常:
return await conn.Connection.QueryAsync<Panel, int?, int?, Panel>( panelsSql, (panel, height, width) => { if (height.HasValue && width.HasValue) { panel.CustomSize = new Common.Objects.CustomPanelSize { Width = width.Value, Height = height.Value }; } return panel; }, new { boardId, userId }, splitOn: "custom_height,custom_width" ).ConfigureAwait(false);
内容的提问来源于stack exchange,提问作者Joe Phillips
相关产品推荐
相关产品推荐

