【发布时间】:2020-01-30 18:35:31
【问题描述】:
我目前正在处理学校管理系统的登录表单。问题是,当我尝试登录时,出现错误:
System.InvalidOperationException:连接未关闭。连接的当前状态是打开的
它说错误出现在代码的第 30 行,但我似乎找不到解决方法。
这是发生错误的方法的代码:
public void LoginTeacher()
{
try
{
command = new SqlCommand("TeacherLogin", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open(); // This is the 30th line.
command.Parameters.AddWithValue("@username", Txt_User.Text);
command.Parameters.AddWithValue("@password", Txt_Pass.Text);
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());
}
finally
{
connection.Close();
}
}
显示该错误后,立即有另一个显示:
System.InvalidOperationException: 阅读器关闭时调用 CheckDataIsReady 的尝试无效
并指向第 71 行,如下所示:
public void Login()
{
try
{
command = new SqlCommand("SP_USER_LOGIN", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
command.Parameters.AddWithValue("@user", Txt_User.Text);
command.Parameters.AddWithValue("@pass", Txt_Pass.Text);
SqlDataReader dataReader = command.ExecuteReader();
if (dataReader.Read())
{
LoginTeacher();
if (dataReader[10].Equals("Admin"))
{
AdminDash adminDash = new AdminDash();
this.Hide();
adminDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString();
adminDash.ShowDialog();
this.Close();
}
之后还有更多代码,但我觉得它不相关,因为它是同一件事,但用户类型不同。
提前致谢!
【问题讨论】:
-
您不应该像那样共享
connection,在使用它的方法中创建它并将其放在using块中 -
请粘贴exact 错误,不要解释它或给我们摘录。但是,是的,JSteward 是对的,您不应该像那样共享连接对象。不要太担心会频繁打开和关闭连接 - ADO.NET 使用 connection pooling,因此实际上您不会像代码看起来那样打开与数据库的物理连接。
-
ADO.NET 在幕后为您处理连接池。最佳做法是为要执行的每个 sql 语句/查询创建一个新连接。通过将连接实例包装在
using块中来确保它们被释放/关闭。这是您的主要问题,因为您的代码似乎试图共享以前关闭的单个连接。 -
在不相关的注释中,不要在您的存储过程名称前加上
sp_。这是 sql server 中内部对象的保留命名约定。另见stackoverflow.com/a/20530262/1260204
标签: c# sql-server ado.net