ASP WebForms连接池修复后出现SqlDataReader已关闭错误求助
解决连接池超时与DataReader关闭的矛盾问题
这个问题我维护老WebForms项目时也踩过一模一样的坑——你想用using确保连接释放解决池溢出,但ASP.NET DataGrid的延迟绑定特性直接给你摆了一道:
问题根源
你原来的代码里,GetCertifications返回的SqlDataReader是依赖打开的连接存活的,虽然加了CommandBehavior.CloseConnection,但外层的using (myConnection)会在方法返回前就把连接关掉。而DataGrid的DataBind()只是把DataReader挂上去,真正读取数据是在ItemDataBound事件触发的时候,这时候连接已经被using销毁了,自然会抛出Invalid attempt to call FieldCount when reader is closed。
最优解决方案:把数据读到内存集合再返回
不要直接返回DataReader,而是先把数据读取到内存中的DataTable(或者强类型集合),这样连接可以及时释放回池,同时DataGrid绑定的是内存数据,后续的ItemDataBound也能正常读取。
1. 修改数据库访问方法(CertificationsSkillsDB.cs)
public DataTable GetCertifications(int userID) { DataTable resultTable = new DataTable(); // 连接和命令都用using包裹,确保自动释放 using (SqlConnection myConnection = new SqlConnection(ConfigurationManager.AppSettings["connectionString"])) using (SqlCommand myCommand = new SqlCommand("GetCertifications", myConnection)) { try { myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.Add(new SqlParameter("@UserID", SqlDbType.Int) { Value = userID }); myConnection.Open(); // 用SqlDataAdapter填充DataTable,读取完成后连接自动释放 using (SqlDataAdapter adapter = new SqlDataAdapter(myCommand)) { adapter.Fill(resultTable); } } catch(SqlException ex) { // 记得把异常对象也记录进去,方便排查具体问题 log.Error("Timesheets error when populating Certifications and Skills grids", ex); return null; } } return resultTable; }
2. 修改BindGrid方法(CertificationSkills.aspx.cs)
public void BindGrid() { try { int userID = SessionState.UserID; DataTable certData = certificationsSkillsDB.GetCertifications(userID); if (certData != null) { CertDataGrid.DataSource = certData; CertDataGrid.DataBind(); } // 技能部分的绑定也按同样方式处理 } catch (Exception Ex) { log.Error("error when populating Certifications and Skills grids", Ex); Message.InnerHtml = "ERROR: There was a problem loading Certifications and Skills entries"; Message.Style["color"] = "red"; } }
3. ItemDataBound逻辑无需修改
原来的ItemDataBound代码读取DbDataRecord的逻辑完全兼容DataTable的行,直接用就行。
额外避坑建议
- 全面检查项目中所有数据库操作代码,把所有直接返回DataReader的地方都改成读取内存集合的方式,彻底杜绝连接泄漏;
- 可以临时调整web.config的连接池配置(比如
max pool size)缓解压力,但这只是临时方案,核心还是要确保连接正确释放; - 所有数据库相关对象(Connection、Command、DataAdapter、DataReader)都要用
using包裹,避免手动关闭遗漏导致的泄漏。
内容的提问来源于stack exchange,提问作者cormacio100
相关产品推荐
相关产品推荐

