ExecuteReader? Connection property has not been initialized

huangapple go评论67阅读模式
英文:

ExecuteReader? Connection property has not been initialized

问题

我正在尝试创建一个登录表单,但当我尝试登录时,我收到一个异常。

我正在使用一个名为 conexaoDB.cs 的单独文件来创建与数据库相关的连接信息。

在按钮外部:

ConexaoDB conexao = new ConexaoDB();

在按钮内部:

try
{
    conexao.conn();

    string sql = "SELECT * FROM users WHERE users_login = @login AND users_pass = @senha";

    SqlCommand command = new SqlCommand(sql);
    command.Parameters.AddWithValue("@login", login);
    command.Parameters.AddWithValue("@senha", senha);

    SqlDataReader reader = command.ExecuteReader();

    if (reader.HasRows)
    {
        MessageBox.Show("弹出下一个窗口 = " + login + " // " + senha);
        tryLogin = true;
    }
    else
    {
        MessageBox.Show("登录或密码无效。");
        tryLogin = false;
    }
}
catch (Exception ex)
{
    MessageBox.Show("捕获异常: " + ex.Message);
}

这仅用于学习SQL连接,不是一个真实的具有真实登录名和密码的数据库。

英文:

I'm trying to do a login form, but when i try to login, I get an exception.

I'm using a separate file called conexaoDB.cs to create the connection with all info about the DB

Outside the button:

ConexaoDB conexao = new ConexaoDB();

Inside the button:

try
{
    conexao.conn();

    string sql = "SELECT * FROM users WHERE users_login = @login AND users_pass = @senha";

    SqlCommand command = new SqlCommand(sql);
    command.Parameters.AddWithValue("@login", login);
    command.Parameters.AddWithValue("@senha", senha);

    SqlDataReader reader = command.ExecuteReader();

    if (reader.HasRows)
    {
        MessageBox.Show("Popup next window = " + login + " // " + senha);
        tryLogin = true;
    }
    else
    {
        MessageBox.Show("Login ou senha inválidos.");
        tryLogin = false;
    }
}
catch (Exception ex)
{
    MessageBox.Show("Catch: " + ex.Message);
}

This is only to learn SQL connection, is not a real database with real logins and passwords

答案1

得分: 0

不要使用ConexaoDB相关的内容,尤其是如果你尝试保持一个连接一直处于打开状态。这是不好的实践,内置的连接池将工作得更好。

以下代码应该可以工作:

try
{
    string sql = "SELECT * FROM users WHERE users_login = @login AND users_pass = @senha";

    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();
        using (var command = new SqlCommand(sql, connection))
        {
            command.Parameters.AddWithValue("@login", login);
            command.Parameters.AddWithValue("@senha", senha);

            using (var reader = command.ExecuteReader())
            {
                tryLogin = reader.HasRows;
                if (tryLogin)
                {
                    // 在消息框中显示密码是极其不良的实践,但我假设这是为了测试
                    MessageBox.Show("弹出下一个窗口 = " + login + " // " + senha);
                }
                else
                {
                    MessageBox.Show("登录或密码无效。");
                }
            }
        }
    }
}
catch (SqlException ex) // 不要捕获过于宽泛的异常,要具体指明
{
    MessageBox.Show("捕获: " + ex.Message);
}

using 语句会负责关闭和处理资源释放,而 SqlConnection 会返回连接池,以便重复使用。

重要
不应该将密码以明文形式存储在数据库中。最佳实践是生成一个带有盐的哈希值,并将哈希值存储在数据库中。在验证用户时,你需要再次计算用户输入的密码的哈希值,然后比较这两个哈希值。这可以确保如果密码表被盗,对攻击者来说是无用的。

英文:

Drop the ConexaoDB stuff, especially if you are trying to keep one connection open at all time. That is bad practice, built-in connection pooling will work much better.

This should work:

try
{
    string sql = "SELECT * FROM users WHERE users_login = @login AND users_pass = @senha";

    using (var connection = new SqlConnection(connectionString)
    {
        connection.Open();
        using (var command = new SqlCommand(sql, connection)
        {
            command.Parameters.AddWithValue("@login", login);
            command.Parameters.AddWithValue("@senha", senha);

            using (var reader = command.ExecuteReader())
            {
                tryLogin = reader.HasRows;
                if (tryLogin)
                {
                    // Extremely bad practice to show password in a messagebox, but I assume it's for test 
                    MessageBox.Show("Popup next window = " + login + " // " + senha);
                }
                else
                {
                    MessageBox.Show("Login ou senha inválidos.");
                }
            }
        }
    }
}
catch (SqlException ex) // Don't catch too broad an exception, be specific
{
    MessageBox.Show("Catch: " + ex.Message);
}

The usings are taking care of closing and disposing and the SqlConnection goes back to the connection pool and will be reused.

Important:
You should not store passwords as clear text in the database. Best practice is to generate a hash, with a salt and store the hashed value in the database. When authenticating the user you compute the hash again on the password input by the user and compare the two hashes. This assures that your password table is useless to an attacker if it gets stolen.

huangapple
  • 本文由 发表于 2023年2月8日 22:34:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75387303.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定