调用SQL存储过程插入ID列表时出现Int32[]无对应映射的ArgumentException错误
问题排查与解决方案
错误原因
你直接将int[]类型的ID数组赋值给了@RestrictionEntityID参数的Value属性,SQL Server .NET 托管提供程序没有对应原生类型支持C#数组的直接映射,因此抛出No mapping exists from object type System.Int32[] to a known managed provider native type错误。
可用解决方案
方案1:使用表值参数(TVP,推荐,支持SQL Server 2008及以上版本)
这是官方推荐的批量传参方式,性能和规范性最优:
- SQL端先创建自定义表类型
CREATE TYPE dbo.IntIdList AS TABLE (Id INT);
- 修改存储过程参数定义
将@RestrictionEntityID参数类型改为你创建的自定义表类型,必须加READONLY修饰:
ALTER PROCEDURE dbo.CreateRestriction @RoleName NVARCHAR(200), @RestrictionEntityTypeCode CHAR(1), @RestrictionEntityID dbo.IntIdList READONLY, @Exclude BIT AS BEGIN -- 业务逻辑中可以直接使用这个表参数,例如: INSERT INTO 你的限制表 (RoleName, RestrictionEntityTypeCode, RestrictionEntityID, Exclude) SELECT @RoleName, @RestrictionEntityTypeCode, Id, @Exclude FROM @RestrictionEntityID END
- 修改C#参数赋值逻辑
替换你原来的paramRestrictionEntityID赋值部分:
// 将ID数组转成符合自定义表类型结构的DataTable DataTable idTable = new DataTable(); idTable.Columns.Add("Id", typeof(int)); int[] idList = Array.ConvertAll(message2.Split(','), int.Parse); foreach (int id in idList) { idTable.Rows.Add(id); } SqlParameter paramRestrictionEntityID = new SqlParameter(); paramRestrictionEntityID.ParameterName = "@RestrictionEntityID"; paramRestrictionEntityID.SqlDbType = SqlDbType.Structured; // 指定为表值参数类型 paramRestrictionEntityID.TypeName = "dbo.IntIdList"; // 与SQL端定义的自定义类型名一致 paramRestrictionEntityID.Value = idTable; cmd.Parameters.Add(paramRestrictionEntityID);
方案2:字符串传参+存储过程内拆分(兼容低版本SQL Server)
如果你的SQL Server版本不支持表值参数,可以用这个兼容方案:
- 将存储过程的
@RestrictionEntityID参数类型改为NVARCHAR(MAX) - C#端直接传原始逗号分隔字符串即可,不需要转int数组:
paramRestrictionEntityID.Value = message2;
- 存储过程内部编写字符串拆分逻辑,将逗号分隔的ID拆成临时表使用即可。
其他代码问题提醒
你当前代码中的do-while循环没有修改message2的值,只要message2初始不为空就会进入死循环,需要调整循环逻辑。@Exclude参数你当前传的是字符串"0",如果存储过程中该参数为BIT类型,建议直接传0或者false,避免不必要的隐式转换风险。
内容的提问来源于stack exchange,提问作者Christian Winters
相关产品推荐
相关产品推荐

