如何在C#中执行返回自定义值的存储过程?报错排查
解决方案
错误原因分析
- 参数传递冲突:代码同时使用了字符串拼接传参和参数化传参,导致SQL命令逻辑混乱,存储过程无法正确接收参数,最终返回空结果集。
- DataReader未定位到数据行:
ExecuteReader()返回的SqlDataReader初始状态指向结果集的前一行,直接读取字段会报错,必须先调用Read()方法移动到有效数据行。
修复后的代码
1. 正确使用参数化调用存储过程
删除字符串拼接中的参数赋值,明确指定命令类型为存储过程,仅通过参数集合传递参数(同时避免SQL注入风险):
// 推荐用using自动管理资源 using (var connection = new SqlConnection("你的数据库连接字符串")) { connection.Open(); using (var command = new SqlCommand("RegistrTankInPack", connection)) { // 关键:指定命令类型为存储过程 command.CommandType = CommandType.StoredProcedure; // 添加与存储过程匹配的参数 command.Parameters.Add(new SqlParameter("@inCode", productCode)); command.Parameters.Add(new SqlParameter("@inNameTemplate", "TOG16RL123456")); command.Parameters.Add(new SqlParameter("@inLine_id", Guid.Parse("2326c2f4-ab2a-40e3-8bac-186617b10fdd"))); command.Parameters.Add(new SqlParameter("@inOperator_id", operatorID)); command.Parameters.Add(new SqlParameter("@inPackage_id", Guid.Empty)); command.Parameters.Add(new SqlParameter("@inQuantity", 0)); // 执行读取 using (var reader = command.ExecuteReader()) { // 先确认有数据行 if (reader.Read()) { // 遍历所有字段 for (int i = 0; i < reader.FieldCount; i++) { packageHeader.Add(reader.GetName(i)); // 处理可能的DBNull值,避免空引用异常 var value = reader.IsDBNull(i) ? string.Empty : reader[i].ToString(); packageData.Add(value); } } else { // 处理无数据返回的情况 throw new InvalidOperationException("存储过程未返回预期数据"); } } } }
2. 关键修复点说明
- 指定
CommandType.StoredProcedure:这让SQL Server知道要执行的是存储过程,而非普通SQL语句,参数传递更可靠。 - 调用
reader.Read():必须先调用此方法移动到结果集的第一行(也是唯一一行),才能安全读取字段值。 - 处理
DBNull:存储过程返回的变量可能为NULL,直接调用ToString()会抛出空引用异常,需要先判断。 - 使用
using语句:自动释放SqlConnection、SqlCommand、SqlDataReader等资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Roman Nichi
相关产品推荐
相关产品推荐

