如何通过Dapper DynamicParameters向SQL存储过程传递int列表参数
报错原因
直接将List<int>类型传给Dapper参数时,Dapper默认会将集合拆分为多个独立的SQL参数,因此会触发「too many arguments」错误。同时用户自定义表类型的参数需要显式指定对应的类型名称,Dapper才能正确识别为表值参数。
解决方案
方法1:转换为DataTable传递(无需显式指定Structured DbType)
即使当前环境无法获取DbType.Structured枚举值,只要将int列表转换为和IntList结构匹配的DataTable,指定参数的TypeName属性即可,Dapper内部会自动完成表值参数的适配:
// 构造与IntList结构一致的DataTable,IntList通常为仅含单个int列的自定义表类型 var agencyIdTable = new DataTable(); // 此处列名必须与数据库中IntList定义的列名完全一致 agencyIdTable.Columns.Add("Value", typeof(int)); foreach (var id in query.AgencyIds) { agencyIdTable.Rows.Add(id); } using var connection = _dbConnectionFactory.GetDefaultServerConnectionString(); var parameters = new DynamicParameters(); parameters.Add("@RequestId", query.RequestId, DbType.DateTime); // 传入构造好的DataTable,typeName填写数据库中自定义表类型的完整名称(带Schema,如dbo.IntList) parameters.Add("@Agencies", agencyIdTable, typeName: "IntList"); return await connection.QueryAsync<TerminalDto>( "SelectTerminals", parameters, commandType: CommandType.StoredProcedure);
注意事项:
- 数据库中
IntList的列名必须和构造的DataTable列名完全一致,否则会出现传值为空的问题 - 如果自定义表类型归属特定Schema,需要把Schema也补在
typeName中,例如dbo.IntList,避免因类型识别失败报错
方法2:兼容方案(极端场景备用)
如果当前环境完全不支持表值参数传递,可以将int列表拼接为逗号分隔的字符串传入,在存储过程内自行拆分字符串得到ID集合:
// C# 侧传参修改为 parameters.Add("@Agencies", string.Join(",", query.AgencyIds));
该方案仅适合ID数量较少的场景,性能弱于表值参数方案。
内容的提问来源于stack exchange,提问作者Masoumeh Karvar
相关产品推荐
相关产品推荐

