c#System.InvalidOperationException:'连接已经打开。'

时间:2018-01-29 12:46:59

标签: c#

我正在为管理应用程序编写Windows窗体登录页面。我的问题是,当我尝试登录时,我收到错误消息

  

System.InvalidOperationException:'连接已经打开。'

任何帮助将不胜感激

public partial class Form1 : Form
{
    MySqlConnection con = new MySqlConnection (@"Database= app2000; Data Source = localhost; User = root; Password =''");
    int i;

    public Form1()
    {
        InitializeComponent();
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
        Application.Exit();
    }

    private void btnLogin_Click(object sender, EventArgs e)
    {
        i = 0;
        con.Open();
        MySqlCommand cmd = con.CreateCommand();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "SELECT * FROM adminlogin WHERE username='" + txtBoxUsername + "'AND password='" + txtBoxPassword + "'";
        cmd.ExecuteNonQuery();
        DataTable dt = new DataTable();
        MySqlDataAdapter da = new MySqlDataAdapter(cmd);
        da.Fill(dt);
        i = Convert.ToInt32(dt.Rows.Count.ToString());

        if (i == 0)
        {
            lblerrorInput.Show();
        }
        else
        {
            this.Hide();
            Main ss = new Main();
            ss.Show();
        }
    }
}

4 个答案:

答案 0 :(得分:2)

不要缓存连接,它是典型的反模式,但在需要时重新创建它

 public partial class Form1 : Form {
   ...
   //DONE: Extract method
   private static bool UserExists(string userName, string password) {
     //DONE: Do not cache connections, but recreate them
     using (MySqlConnection con = new MySqlConnection (@"...") {
        con.Open();

        //DONE: wrap IDisposable into using
        using (MySqlCommand cmd = con.CreateCommand()) {
          cmd.CommandType = CommandType.Text;

          //DONE: Make query being readable
          //DONE: Make query being parametrized
          cmd.CommandText = 
            @"SELECT * 
                FROM adminlogin 
               WHERE username = @UserName 
                 AND password = @PassWord"; // <- A-A-A! Password as a plain text!

          //TODO: the simplest, but not the best solution: 
          // better to create parameters explicitly
          // cmd.Parameters.Add(...)
          cmd.Parameters.AddWithValue("@UserName", txtBoxUsername);   
          cmd.Parameters.AddWithValue("@PassWord", txtBoxPassword);   

          // If we have at least one record, the user exists
          using (var reader = cmd.ExecuteReader()) {
            return (reader.Read()); 
          }
        }
     }   
   }

最后

   private void btnLogin_Click(object sender, EventArgs e) {
     if (!UserExists(txtBoxUsername.Text, txtBoxPassword.Text))  
       lblerrorInput.Show();
     else {
       Hide();
       Main ss = new Main();
       ss.Show();
     }
   }

答案 1 :(得分:0)

您忘记关闭连接,最后使用con.Close()关闭连接,并在下次事件触发时避免此错误。

答案 2 :(得分:0)

您的代码中存在一些错误。

  • 完成流程后应关闭sql连接。
  • 我建议您在完成数据库操作后使用using语句来处置连接实例。
  • 此外,您应该使用命令参数来阻止Sql注入。

您可以像这样声明连接字符串;

private string _connectionString = @"Database= app2000; Data Source = localhost; User = root; Password =''";

方法部分看起来像;

using (var con = new MySqlConnection(_connectionString))
{
    i = 0;
    con.Open();
    MySqlCommand cmd = con.CreateCommand();
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = "SELECT * FROM adminlogin WHERE username = @username and password = @password";
    cmd.Parameters.AddWithValue("@username", txtBoxUsername);
    cmd.Parameters.AddWithValue("@password", txtBoxPassword);
    cmd.ExecuteNonQuery();
    DataTable dt = new DataTable();
    MySqlDataAdapter da = new MySqlDataAdapter(cmd);
    da.Fill(dt);
    i = Convert.ToInt32(dt.Rows.Count.ToString());

    if (i == 0)
    {
        lblerrorInput.Show();
    }
    else
    {
        this.Hide();
        Main ss = new Main();
        ss.Show();
    }
    con.Close();
}

答案 3 :(得分:0)

首先,不要缓存Connection个对象。这是一种可怕的做法,每次我接受新工作并继承代码时,我都必须回去修复它。大多数数据库访问类都实现IDisposable,因此请使用using并利用它来保持代码清洁。仅供参考,ReadersAdapters也是IDisposable,因此您也可以对它们进行同样的操作。

string command = "select stuff from mydata";
string connection = GetConnectionStringFromEncryptedConfigFile();

    using (var conn = new SqlConnection(connection))
    {
      using (var cmd = new SqlCommand(command, conn))
       {
          cmd.Connection.Open();
          //do stuff            
       }
    }

其次,如果您强制使用缓存连接(即您继承了可怕的代码并且还没有时间修复它),请先检查State

if(conn.State != System.Data.ConnectionState.Open)
{
   conn.Open();
}

请注意,除了OpenClosed之外,还有很多其他状态,如果您尝试打开繁忙的连接,您仍会遇到错误。将IDisposable实现与using一起使用仍然是一种更明智的方法,因此您不必担心这类事情。