调用SqlDataReader.Read触发READER IS CLOSED逐行报错问题求助
错误原因排查
- 核心触发原因:第二个查询的读取循环中变量名书写错误,你为第二个查询创建的DataReader变量是
r1,但读取taxrate、tax字段时用了r对象,这个r大概率是其他业务逻辑中已经关闭的DataReader实例,每次访问就会触发Reader已关闭的报错。 - 资源释放顺序错误:第二个查询执行完成后,你先执行了
conn.Close()关闭数据库连接,再关闭DataReader,DataReader的运行必须依赖开放的数据库连接,连接提前关闭会直接强制终止Reader的读取能力。 - 全局连接复用风险:你使用了全局的
conn连接对象,若其他逻辑同时操作该连接,可能会出现连接被提前关闭、状态异常的问题。 - 额外安全隐患:直接拼接SQL语句传参,存在SQL注入风险,可能导致数据库数据泄露、被篡改。
修复方案
推荐使用using块自动管理数据库连接、命令、DataReader的资源释放,无需手动执行Close操作,避免出现资源释放顺序错误的问题,修复后代码如下:
void otherdata() { // 按需创建连接,不要复用全局连接,连接字符串请替换为你实际的配置 using (SqlConnection conn = new SqlConnection("你的数据库连接字符串")) { conn.Open(); // 执行第一个查询 using (SqlCommand cmd = new SqlCommand()) { cmd.Connection = conn; // 改用参数化查询,避免SQL注入 cmd.CommandText = @"select customer.cust_name,customer.cust_id,purchase_details.purchase_id,purchase_details.pdate,purchase_details.subtotal,purchase_details.total,purchase_details.supp_bill_id from Purchase_details inner join customer on purchase_details.supplier_id=customer.cust_id where id = @pd"; cmd.Parameters.AddWithValue("@pd", pd); using (SqlDataReader r1 = cmd.ExecuteReader()) { while (r1.Read()) { cbsupplier.Text = r1["cust_name"].ToString(); txtdate.Value = Convert.ToDateTime(r1["pdate"]); txtsubtotal.Text = r1["subtotal"].ToString(); custid.Text = r1["cust_id"].ToString(); MessageBox.Show("pochalo"); } } } // 执行第二个查询 using (SqlCommand cmd2 = new SqlCommand()) { cmd2.Connection = conn; cmd2.CommandText = "select * from purchase where purchase_id = @pd"; cmd2.Parameters.AddWithValue("@pd", pd); using (SqlDataReader r2 = cmd2.ExecuteReader()) { while (r2.Read()) { txtadjust.Text = r2["adjustment"].ToString(); // 修正变量名错误,用当前查询的Reader读取字段 cbtaxrate.Text = r2["taxrate"].ToString(); txttax.Text = r2["tax"].ToString(); } } } } }
内容的提问来源于stack exchange,提问作者Amol Panchal
相关产品推荐
相关产品推荐

