开发Windows Forms管理员登录页遇System.InvalidOperationException:连接已打开错误求助
Hey there, let's break down why you're seeing that System.InvalidOperationException: 'The connection is already open.' error and fix it, along with some other critical issues in your code.
What's Causing the Connection Error?
Your MySqlConnection con is declared as a class-level field. That means it's created once when the form loads, and if you click the login button more than once (or if the connection wasn't closed properly after the first use), the second attempt to call con.Open() will throw the error—since the connection is already open from the first click.
On top of that, your code has two other big issues:
- SQL Injection Vulnerability: You're directly concatenating text box values into your SQL query. This is a huge security risk that attackers can exploit to access or modify your database.
- Incorrect Text Box Value Access: You're using
txtBoxUsernameinstead oftxtBoxUsername.Text(same for the password box)—so you're passing the control object itself into the query, not the actual input text the user typed.
Fixed Code with Explanations
Here's the revised code that fixes all these problems:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void btnClose_Click(object sender, EventArgs e) { Application.Exit(); } private void btnLogin_Click(object sender, EventArgs e) { // Use a local connection wrapped in 'using' to auto-manage disposal/closure using (MySqlConnection con = new MySqlConnection(@"Database=app2000; Data Source=localhost; User=root; Password=''")) { con.Open(); // Use parameterized query to prevent SQL injection string query = "SELECT * FROM adminlogin WHERE username = @Username AND password = @Password"; MySqlCommand cmd = new MySqlCommand(query, con); // Add parameters with actual text box values cmd.Parameters.AddWithValue("@Username", txtBoxUsername.Text); cmd.Parameters.AddWithValue("@Password", txtBoxPassword.Text); DataTable dt = new DataTable(); MySqlDataAdapter da = new MySqlDataAdapter(cmd); da.Fill(dt); if (dt.Rows.Count == 0) { lblerrorInput.Show(); } else { this.Hide(); Main ss = new Main(); ss.Show(); } } // 'using' block will automatically close and dispose the connection here } }
Key Improvements:
- Local Connection with
using: By declaring the connection inside the login method and wrapping it in ausingblock, we ensure the connection is automatically closed and disposed as soon as we're done with it—no more "already open" errors, even if the user clicks login multiple times. - Parameterized Queries: Instead of concatenating user input, we use
@Usernameand@Passwordparameters. This eliminates SQL injection risks and handles special characters in inputs correctly. - Correct Text Box Access: We use
txtBoxUsername.Textto get the actual input value from the text box, not the control object itself. - Removed Unnecessary Code: The
ExecuteNonQuery()call was redundant here—DataAdapter.Fill()handles executing the query and populating the DataTable for us.
Bonus Tips:
- Never Store Plain Text Passwords: Storing passwords as plain text in your database is a massive security flaw. Always hash passwords (using something like bcrypt) before storing them, and hash the user's input to compare against the stored hash.
- Handle Connection Exceptions: Add a
try-catchblock around the database code to handle things like invalid credentials, database downtime, or network issues gracefully (instead of crashing the app).
内容的提问来源于stack exchange,提问作者Arne Daniel Iselvmo Bjerk

