Dapper调用含条件select的存储过程时出现类型转换错误问题
问题原因
该问题完全由Dapper的性能缓存机制导致,核心逻辑如下:
- Dapper为了降低重复查询的反序列化开销,会以「查询语句/存储过程标识 + 返回映射的实体类型」作为缓存键,缓存首次查询时生成的反序列化委托
- 生成反序列化委托时,Dapper会基于首次查询返回的结果集字段顺序,建立「列索引→实体属性」的绑定关系,后续相同缓存键的查询都会复用这个绑定逻辑,不会重新读取结果集的字段元数据
- 你的场景中首次查询走if分支,返回列顺序为
Id、Title、Description,生成的绑定逻辑为「第0列赋值给Id属性、第1列赋值给Title属性」;第二次查询走else分支,返回列顺序变成Title、Id、Description,Dapper仍然按照原绑定逻辑取值,会将long类型的Id值赋值给string类型的Title属性(或反之),最终触发类型转换异常。
解决方案
- 最优方案:保持同个存储过程中所有返回相同结构的查询语句的字段顺序完全一致,也就是你已经验证过的规避方案,完全不损耗性能,改造成本极低
- 若确实无法调整SQL字段顺序,可使用Dapper 2.0及以上版本提供的配置项,开启全局按列名绑定:
SqlMapper.Settings.UseColumnNamesForBinding = true,开启后Dapper会基于列名而非列索引做绑定,不受字段顺序影响,仅会略微增加反序列化的性能开销 - 不推荐方案:每次查询后手动清除对应缓存,调用
SqlMapper.RemoveQueryCache()方法清除缓存,该方案会完全丧失Dapper的缓存性能优势,仅可用于临时验证问题
内容的提问来源于stack exchange,提问作者Shanid
相关产品推荐
相关产品推荐

