在创建密码更改表单时获得异常

时间:2013-10-28 20:37:57

标签: c# sql-server exception

我正在创建密码更改表单。当我执行表单并填写文本框时,它会给出一条带有There is already and open DataReader associated with this command which must be closed first消息的例外。

他是我正在使用的代码:

private bool CompareStrings(string string1, string string2)
        {
            return String.Compare(string1, string2, true, System.Globalization.CultureInfo.InvariantCulture) == 0 ? true : false;
        }

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            SqlConnection con1 = new SqlConnection();
            con1.ConnectionString = "data source=.;Initial catalog=inventory;Integrated Security=true";
            con1.Open();

            SqlCommand cmd = new SqlCommand("SELECT ISNULL(username, '') AS username, ISNULL(password,'') AS password FROM login WHERE username='" + textBox1.Text + "' and password='" + textBox2.Text + "'", con1);

            SqlDataReader dr = cmd.ExecuteReader();

            string userText = textBox1.Text;
            string passText = textBox2.Text;

            while (dr.Read())
            {
                if (this.CompareStrings(dr["username"].ToString(), userText) &&
                    this.CompareStrings(dr["password"].ToString(), passText))
                {
                    SqlCommand cmd2 = new SqlCommand("UPDATE login SET password='" + textBox3.Text + "'where username='" + textBox1.Text + "'", con1);
                    cmd2.ExecuteNonQuery();
                    MessageBox.Show("Password Changed Successfully");
                }
                else
                {
                    MessageBox.Show("Incorrect Old password");                        
                }

            }

            dr.Close();

            con1.Close();

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

2 个答案:

答案 0 :(得分:2)

在同一连接上打开SqlDataReader时,无法执行命令。您可以执行以下两项操作之一来更改代码:

  1. 创建第二个连接并在第二个连接上运行更新查询。

  2. 存储阅读器中的数据,关闭阅读器,然后更新所有数据。在您的情况下,您可以使用Username in (<yourlisthere>)

  3. 存储所有用户名以在一个更新查询中更新和更新它们

答案 1 :(得分:2)

当您打开DataReader时,该连接仅提供来自DataReader的请求。用于更新登录表的SqlCommand无法运行。

除非您将此添加到您的connectionstring

MultipleActiveResultSets = True;

Here you can find the reference to MARS

关于DataReader的here the words from MSDN

  

在使用SqlDataReader时,关联的SqlConnection是   忙于服务SqlDataReader,没有其他操作可以   在SqlConnection上执行而不是关闭它。情况就是这样   直到调用SqlDataReader的Close方法。例如,   在调用Close之前,您无法检索输出参数。

作为旁注,但非常重要。不要使用字符串连接来构建sql命令。始终使用参数化查询

string cmdText = "UPDATE login SET password=@pwd where username=@usr";
using(SqlCommand cmd2 = new SqlCommand(cmdText, con1))
{
    cmd2.Parameters.AddWithValue("@pwd", textBox3.Text);
    cmd2.Parameters.AddWithValue("@usr", textBox1.Text);
    cmd2.ExecuteNonQuery();    
}

参数化查询可以避免Sql Injection问题,让您简化命令文本 对于代码开头的SELECT查询也是如此。不要相信来自您用户的输入

您应该注意的另一个问题是在数据库中存储明文密码。从安全角度来看,这被认为是一种非常糟糕的做法。您应该为您的密码应用哈希函数并存储结果。在检查正确的密码时,您在用户输入上重复哈希函数,并根据存储在数据库中的哈希密码检查结果