C#登录时System.InvalidOperationException连接未关闭报错求助
问题根因
你遇到的连接未关闭,当前状态为打开异常完全是代码里连接对象使用逻辑错误导致的,核心问题有3个:
- 全局连接对象误用:你在窗体构造函数初始化了全局
SqlConnection connection,但Login、LoginTeacher方法里明明用using创建了局部连接cnn,给SqlCommand绑定的却是全局的connection,全程没有用到局部连接,全局连接每次调用Open()后从未关闭,第二次调用就会触发异常。 - 登录逻辑重复调用:登录按钮点击事件里先调用
LoginTeacher,又调用Login,且Login方法校验通过后还会再次调用LoginTeacher,全局连接被多次尝试打开,直接触发报错。 - 资源释放不规范:
SqlDataReader用完未主动释放,using块会在作用域结束后自动释放连接,你在finally里重复写cnn.Close()属于多余操作。
修复步骤
- 删掉全局
connection对象,所有数据库操作都使用using块创建的局部连接,避免连接复用导致的状态冲突 - 删掉重复的登录调用:登录按钮事件里只保留
Login()调用,同时删掉Login方法内部的LoginTeacher()调用 - 给
SqlDataReader也加上using块,自动释放读取器资源 - SqlCommand绑定
using块里的局部连接,不用全局对象
修复后核心代码示例
public LoginForm() { InitializeComponent(); // 删掉全局connection初始化,不需要全局连接对象 } #region Methods public void LoginTeacher() { // 只在Teacher角色需要单独校验的时候才调用这个方法,正常登录逻辑里不需要重复调用 using (SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["CS"].ConnectionString)) { try { // 绑定局部cnn连接,不是全局connection SqlCommand command = new SqlCommand("TeacherLogin", cnn); command.CommandType = CommandType.StoredProcedure; cnn.Open(); command.Parameters.AddWithValue("@username", Txt_User.Text); command.Parameters.AddWithValue("@password", Txt_Pass.Text); // 给DataReader加using自动释放 using (SqlDataReader dataReader = command.ExecuteReader()) { if (dataReader.Read()) { TeacherDash teacherDash = new TeacherDash(); this.Hide(); teacherDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString(); teacherDash.ShowDialog(); this.Close(); } } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } // 删掉多余的cnn.Close(),using会自动处理 } } public void Login() { using (SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["CS"].ConnectionString)) { try { // 绑定局部cnn连接 SqlCommand command = new SqlCommand("SP_USER_LOGIN", cnn); command.CommandType = CommandType.StoredProcedure; cnn.Open(); command.Parameters.AddWithValue("@user", Txt_User.Text); command.Parameters.AddWithValue("@pass", Txt_Pass.Text); using (SqlDataReader dataReader = command.ExecuteReader()) { if (dataReader.Read()) { // 删掉重复的LoginTeacher()调用 string role = dataReader[10].ToString(); if (role.Equals("Admin")) { AdminDash adminDash = new AdminDash(); this.Hide(); adminDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString(); adminDash.ShowDialog(); this.Close(); } else if (role.Equals("Teacher")) { // 如果Teacher需要额外校验再调用LoginTeacher,否则直接跳转 TeacherDash teacherDash = new TeacherDash(); this.Hide(); teacherDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString(); teacherDash.ShowDialog(); this.Close(); } else if (role.Equals("Accounts")) { AccountsDash accountsDash = new AccountsDash(); this.Hide(); accountsDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString(); accountsDash.ShowDialog(); this.Close(); } else if (role.Equals("Addmission")) { AdmissionDash admissionDash = new AdmissionDash(); this.Hide(); admissionDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString(); admissionDash.ShowDialog(); this.Close(); } } else if (string.IsNullOrWhiteSpace(Txt_User.Text) && string.IsNullOrWhiteSpace(Txt_Pass.Text)) { MessageBox.Show("用户名和密码均为空", "空字段", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (string.IsNullOrWhiteSpace(Txt_User.Text)) { MessageBox.Show("请输入用户名", "用户名为空", MessageBoxButtons.OK, MessageBoxIcon.Information); } else if (string.IsNullOrWhiteSpace(Txt_Pass.Text)) { MessageBox.Show("请输入密码", "密码为空", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show("用户名或密码错误", "登录失败", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } } #endregion private void Btn_Login_Click(object sender, EventArgs e) { // 删掉重复的LoginTeacher调用,只保留Login Login(); } private void pictureBox4_Click(object sender, EventArgs e) { this.Close(); }
内容的提问来源于stack exchange,提问作者Noman ßaloch
相关产品推荐
相关产品推荐

