我正在为管理应用程序编写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();
}
}
}
答案 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)
您的代码中存在一些错误。
using
语句来处置连接实例。您可以像这样声明连接字符串;
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
并利用它来保持代码清洁。仅供参考,Readers
和Adapters
也是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();
}
请注意,除了Open
和Closed
之外,还有很多其他状态,如果您尝试打开繁忙的连接,您仍会遇到错误。将IDisposable
实现与using
一起使用仍然是一种更明智的方法,因此您不必担心这类事情。