循环批量插入数据时遇DataReader未关闭错误,求解决方法
解决SqlCommand执行批量插入时的DataReader关联错误
你遇到的错误提示看似和DataReader有关,但实际核心问题是循环中重复向同一个SqlCommand对象添加参数。第一次循环时参数集合添加了@name和@category,第二次循环再次调用AddWithValue会导致参数重复,触发内部执行异常,进而抛出了误导性的DataReader相关错误。
推荐修改方案:预定义参数,循环内赋值
这种方式效率更高,避免重复创建命令对象,同时彻底解决参数重复问题:
List<TransactionAccount> accounts = new List<TransactionAccount>(); try { using (var con = new SqlConnection(connectionString)) { string query = "INSERT INTO Accounts (name, category) VALUES (@name, @category)"; // 用using包裹SqlCommand,确保资源自动释放 using (var cmd = new SqlCommand(query, con)) { // 预先定义参数并指定类型(比AddWithValue更安全,避免类型推断问题) cmd.Parameters.Add("@name", SqlDbType.NVarChar); cmd.Parameters.Add("@category", SqlDbType.NVarChar); con.Open(); foreach (TransactionAccount account in accounts) { // 循环内仅更新参数值,不重复添加参数 cmd.Parameters["@name"].Value = account.name; cmd.Parameters["@category"].Value = account.category; cmd.ExecuteNonQuery(); } } } // using块会自动关闭连接,无需手动调用con.Close() } catch (Exception ex) { // 这里建议添加异常处理逻辑,比如记录日志或输出错误信息 Console.WriteLine(ex.Message); }
另一种简单方案:循环内新建SqlCommand
如果不想预定义参数,也可以每次循环创建新的SqlCommand对象(效率略低,但实现简单):
List<TransactionAccount> accounts = new List<TransactionAccount>(); try { using (var con = new SqlConnection(connectionString)) { con.Open(); string query = "INSERT INTO Accounts (name, category) VALUES (@name, @category)"; foreach (TransactionAccount account in accounts) { using (var cmd = new SqlCommand(query, con)) { cmd.Parameters.AddWithValue("@name", account.name); cmd.Parameters.AddWithValue("@category", account.category); cmd.ExecuteNonQuery(); } } } } catch (Exception ex) { Console.WriteLine(ex.Message); }
关键注意事项
- 不要手动调用
con.Close():using语句块会自动释放连接资源,无论是否发生异常。 - 优先避免
AddWithValue:该方法可能导致SQL Server的类型推断错误,推荐显式指定参数类型。 - 用using包裹SqlCommand:确保命令对象的资源被正确释放,避免潜在的资源泄漏。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

