C# System.InvalidOperationException:&x27;连接未关闭';

C# System.InvalidOperationException:&x27;连接未关闭';,c#,sql,sql-server,winforms,C#,Sql,Sql Server,Winforms,我正在使用C#Form和SQL Server。我登录时遇到问题 “System.InvalidOperationException:'连接未关闭' 我无法解决这个问题。我想我添加了很多“con.Open()”。但我尝试了很多方法,但仍然犯了这个错误。我想,我又删除了一个Open和close,是真的吗 private void buttonLogin_Click(object sender, EventArgs e) { con.Open(); if (String.IsNull

我正在使用C#Form和SQL Server。我登录时遇到问题

“System.InvalidOperationException:'连接未关闭'

我无法解决这个问题。我想我添加了很多“
con.Open()
”。但我尝试了很多方法,但仍然犯了这个错误。我想,我又删除了一个Open和close,是真的吗

private void buttonLogin_Click(object sender, EventArgs e)
{
    con.Open();

    if (String.IsNullOrEmpty(textBoxUserName.Text))
    {
        MessageBox.Show("Username can't be empty");
        textBoxUserName.Focus();
        con.Close();
    }
    if (String.IsNullOrEmpty(textBoxPassword.Text))
    {
        MessageBox.Show("Password can't be empty");
        textBoxPassword.Focus();
        con.Close();
    }

    else
    {
        con.Open();
        SqlCommand SelectCommand = new SqlCommand("SELECT * FROM Users WHERE  username ='" + textBoxUserName.Text.Trim() + "' and password= '" + textBoxPassword.Text.Trim() + "'");
        SqlDataReader myReader;
        myReader = SelectCommand.ExecuteReader();
        int count = 0;
        string userRole = string.Empty;
        while (myReader.Read())
        {
            count = count + 1;
            userRole = myReader["userrank"].ToString();
        }

        if (count == 1)
        {

            if (userRole =="admin" )
            {
                Form1 form = new Form1();
                this.Hide();
                form.Show();
                con.Close();
            }
            else
            {
                UI ui = new UI();
                this.Hide();
                ui.Show();
                con.Close();
            }
            myReader.Close();
        }
        else
        {
            MessageBox.Show("Check your username or password");
            con.Close();
        }           
    }       
}

您可以在打开连接之前检查状态,因为打开打开的连接将失败

if(con.State == ConnectionState.Closed)
{
    con.Open();
}

旁注:最佳实践是

string command = "SELECT * FROM Users WHERE  username = @username and password = @password";
using (SqlConnection con = new SqlConnection(ConnectionString))
{
    con.Open();
    using (SqlCommand cmd = new SqlCommand(command, con))
    {
        cmd.Parameters.Add("@username", SqlDbType.VarChar).Value = textBoxUserName.Text.Trim();
        cmd.Parameters.Add("@password", SqlDbType.VarChar).Value = textBoxPassword.Text.Trim();
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                count = count + 1;
                userRole = myReader["userrank"].ToString();
            }
        }
    }
}
  • 使用
    时,您不必关心状态、关闭和处理连接
  • 使用参数避免注入攻击

您可以在打开连接之前检查状态-因为打开打开的连接将失败

if(con.State == ConnectionState.Closed)
{
    con.Open();
}

旁注:最佳实践是

string command = "SELECT * FROM Users WHERE  username = @username and password = @password";
using (SqlConnection con = new SqlConnection(ConnectionString))
{
    con.Open();
    using (SqlCommand cmd = new SqlCommand(command, con))
    {
        cmd.Parameters.Add("@username", SqlDbType.VarChar).Value = textBoxUserName.Text.Trim();
        cmd.Parameters.Add("@password", SqlDbType.VarChar).Value = textBoxPassword.Text.Trim();
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                count = count + 1;
                userRole = myReader["userrank"].ToString();
            }
        }
    }
}
  • 使用
    时,您不必关心状态、关闭和处理连接
  • 使用参数避免注入攻击

您似乎有一些多余的代码。无需在开始时打开连接,然后在不使用连接的情况下再次关闭连接

而且,如果它击中你的第一个if,它可能会击中你的else语句

我认为下面的代码可以解决您的问题,通过点击第一个if语句可以关闭con对象。当然,假设您已经全局实例化了con对象

private void buttonLogin_Click(object sender, EventArgs e)
{
    if (String.IsNullOrEmpty(textBoxUserName.Text))
    {
        MessageBox.Show("Username can't be empty");
        textBoxUserName.Focus();
    }
    else if (String.IsNullOrEmpty(textBoxPassword.Text))
    {
        MessageBox.Show("Password can't be empty");
        textBoxPassword.Focus();
    }
    else
    {
        using (SqlConnection con = new SqlConnection(ConnectionString))
        {
            SqlCommand SelectCommand = new SqlCommand("SELECT * FROM Users WHERE  
            username ='" + textBoxUserName.Text.Trim() + "' and password= '" + textBoxPassword.Text.Trim() + "'");
            SqlDataReader myReader;
            myReader = SelectCommand.ExecuteReader();
            int count = 0;
            string userRole = string.Empty;
            while (myReader.Read())
            {
                count = count + 1;
                userRole = myReader["userrank"].ToString();
            }

            if (count == 1)
            {

                if (userRole =="admin" )
                {
                    Form1 form = new Form1();
                    this.Hide();
                    form.Show();
                    con.Close();
                }
                else
                {
                    UI ui = new UI();
                    this.Hide();
                    ui.Show();
                    con.Close();
                }
                myReader.Close();
            }
            else
            {
                MessageBox.Show("Check your username or password");
                con.Close();
            }           
        } 
    }      
}

看起来你有一些多余的代码。没有必要在开始时打开连接,然后再关闭它,而不必使用连接

而且,如果它击中你的第一个if,它可能会击中你的else语句

我认为下面的代码可以解决您的问题,通过点击第一个if语句可以关闭con对象。当然,假设您已经全局实例化了con对象

private void buttonLogin_Click(object sender, EventArgs e)
{
    if (String.IsNullOrEmpty(textBoxUserName.Text))
    {
        MessageBox.Show("Username can't be empty");
        textBoxUserName.Focus();
    }
    else if (String.IsNullOrEmpty(textBoxPassword.Text))
    {
        MessageBox.Show("Password can't be empty");
        textBoxPassword.Focus();
    }
    else
    {
        using (SqlConnection con = new SqlConnection(ConnectionString))
        {
            SqlCommand SelectCommand = new SqlCommand("SELECT * FROM Users WHERE  
            username ='" + textBoxUserName.Text.Trim() + "' and password= '" + textBoxPassword.Text.Trim() + "'");
            SqlDataReader myReader;
            myReader = SelectCommand.ExecuteReader();
            int count = 0;
            string userRole = string.Empty;
            while (myReader.Read())
            {
                count = count + 1;
                userRole = myReader["userrank"].ToString();
            }

            if (count == 1)
            {

                if (userRole =="admin" )
                {
                    Form1 form = new Form1();
                    this.Hide();
                    form.Show();
                    con.Close();
                }
                else
                {
                    UI ui = new UI();
                    this.Hide();
                    ui.Show();
                    con.Close();
                }
                myReader.Close();
            }
            else
            {
                MessageBox.Show("Check your username or password");
                con.Close();
            }           
        } 
    }      
}
使用构造

using (con)
{
  //do your work
}
这将在成功和异常情况下自动处理连接

使用construct

using (con)
{
  //do your work
}

这将在成功和出现异常时自动处理连接解决方案:不要重复使用连接,而是始终在使用连接的位置(在方法中)打开和关闭连接,最好使用
using
-语句以确保它始终被处理/关闭。您应该使用,并且应该创建(和处理)在尽可能小的范围内建立连接,而不是重用
con
对象。
SqlConnection
实例只是句柄,而不是物理连接,您可以在几乎没有任何资源成本的情况下打开和关闭它们。重用它们只会给您带来麻烦——首先,您如何处理断开的连接?(答案是:非常尴尬,如果你只有一个实例。)我不理解
Form1 form=new Form1();
UI=new UI()
行。你被这么多打开/关闭操作弄糊涂了。为什么在进行正常验证时还要麻烦打开呢?请始终使用
使用
,这样你才能始终确定。@如果管理员想要登录,请传递Form1或用户想要登录UI。解决方案:不要重复使用你的连接,而是始终在使用它的地方(在方法中)打开和关闭它,最好使用
using
-语句来确保它始终被释放/关闭。您应该使用,并且应该创建(和释放)在尽可能小的范围内建立连接,而不是重用
con
对象。
SqlConnection
实例只是句柄,而不是物理连接,您可以在几乎没有任何资源成本的情况下打开和关闭它们。重用它们只会给您带来麻烦——首先,您如何处理断开的连接?(答案是:非常尴尬,如果你只有一个实例。)我不理解
Form1 form=new Form1();
UI=new UI()
行。你把自己弄糊涂了,有这么多打开/关闭的代码。为什么在进行正常验证时还要麻烦打开呢?始终使用
使用
,这样你就可以始终确定了。@SeM如果管理员想登录,请传递Form1或用户想要登录UI。我尝试过了,但现在我接受了这个命令:“System.InvalidOperationException:”连接未启动“我根据@fubo关于“使用”语句的灵感编辑了我的答案。你必须将“con”对象的全局实例化移到“using”行。我尝试了一下,但现在我接受了以下内容:“System.invalidoOperationException:‘Connection dont start’”我根据@fubo关于“使用”的灵感编辑了我的答案”语句。您必须将“con”对象的全局实例化移动到“using”行。
con
还应在using中声明以正确处置
using(SqlConnection con=new-SqlConnection(ConnectionString))
还应在using中声明以正确处置
using(SqlConnection con=newsqlconnection(ConnectionString))