ASP.NET后台C#按钮第三次点击无响应问题求助
问题分析与解决方案
核心问题原因
- DataReader读取丢失数据:你先调用了
rque.Read(),这会将DataReader的指针移动到第一行,之后dt.Load(rque)只会读取剩余的行,导致DataTable中缺少第一行数据。当计数变量c递增到等于DataTable的行数时,访问dt.Rows[c]会抛出索引越界异常,导致页面回发失败,按钮事件无法正常触发。 - 计数变量未持久化:
c和qno是页面级字段,ASP.NET每次回发都会重新创建页面实例,这些变量会被重置。你当前前两次点击有效,大概率是初始值设为-1,但后续回发后变量状态丢失,或是异常导致逻辑中断。 - SQL注入风险:直接用字符串拼接SQL语句,存在严重的SQL注入漏洞,同时可能因为特殊字符导致查询失败。
修复后的代码示例
后台代码(修正版)
// 用ViewState持久化计数变量,避免回发重置 private int C { get { return ViewState["C"] != null ? (int)ViewState["C"] : -1; } set { ViewState["C"] = value; } } private int Qno { get { return ViewState["Qno"] != null ? (int)ViewState["Qno"] : 0; } set { ViewState["Qno"] = value; } } protected void NextButton_Click(object sender, EventArgs e) { // 递增计数 C++; Qno++; // 使用参数化查询,避免SQL注入 string sql = "select * from questions where course=@course and [group]=@group and semester=@semester"; using (SqlCommand lque = new SqlCommand(sql, con)) { lque.Parameters.AddWithValue("@course", cour); lque.Parameters.AddWithValue("@group", gr); lque.Parameters.AddWithValue("@semester", sem); DataTable dt = new DataTable(); try { con.Open(); dt.Load(lque.ExecuteReader()); } finally { con.Close(); } // 检查是否还有数据可显示 if (dt.Rows.Count > 0 && C < dt.Rows.Count) { QuestionNo.Text = Qno.ToString(); DataRow row = dt.Rows[C]; Question.Text = row.Field<string>(4); RadioButton1.Text = row.Field<string>(5); RadioButton2.Text = row.Field<string>(6); RadioButton3.Text = row.Field<string>(7); RadioButton4.Text = row.Field<string>(8); } else { // 无更多数据时的处理 QuestionNo.Text = "已到最后一题"; Question.Text = ""; RadioButton1.Text = ""; RadioButton2.Text = ""; RadioButton3.Text = ""; RadioButton4.Text = ""; // 重置计数以便重新开始 C = -1; Qno = 0; } } }
关键修复点
- ViewState持久化变量:将
c和qno改为ViewState属性,确保回发时变量值不会丢失。 - 移除多余的DataReader.Read():直接用
dt.Load(lque.ExecuteReader())读取所有数据,避免丢失第一行。 - 参数化SQL查询:替换字符串拼接为参数化查询,消除SQL注入风险,同时避免特殊字符导致的查询错误。
- 索引越界检查:在访问DataTable行之前,先检查
C是否小于总行数,避免抛出异常导致页面回发失败。 - 资源释放:使用
using块管理SqlCommand,确保数据库连接正确关闭。
额外建议
- 可以将DataTable缓存到ViewState或Session中,避免每次点击都查询数据库,提升性能:比如第一次查询后将dt保存到ViewState,后续点击直接从ViewState读取。
- 调试时可以在按钮事件开头添加断点,查看
C的值和DataTable的行数,确认是否出现索引越界的情况。
内容的提问来源于stack exchange,提问作者Ramesh
相关产品推荐
相关产品推荐

