首页 > 解决方案 > 哪个博士是打开的?(System.InvalidOperationException:'已经有一个打开的 DataReader 与此命令关联,必须先关闭。')

问题描述

我收到了以下异常(System.InvalidOperationException:'已经有一个打开的 DataReader 与此命令关联,必须先关闭。')我不知道如何修复它。我会感谢一些帮助

    private void button2_Click(object sender, EventArgs e) // PLACING ORDERS
    {
        int qty1 = 0;
        int cmd2_num;
        SqlConnection con = new SqlConnection("Data Source=.\\sqlexpress;Initial Catalog=adventureworks2012;" + "User ID=sarr**strong *strong text*text**;Password=1234");
        con.Open();
        
        SqlCommand cmd1 = new SqlCommand ("select Quantity from Production.ProductInventory where productid ='" + int.Parse(textBox1.Text) + "'",con);
        SqlCommand cmd2 = new SqlCommand(
            "'UPDATE Production.ProductInventory" +
            "SET Quantity -='" + qty +
            "'WHERE ProductId = '" + textBox1.Text + "'",con);

        SqlDataReader dr = cmd1.ExecuteReader();
        
        
        while (dr.Read())
        {
            qty1 = int.Parse(dr.GetValue(0).ToString());
        }
        if (qty1 >= qty)
        {
            cmd2_num = cmd2.ExecuteNonQuery();
        }
        else
        {
            MessageBox.Show("unfortunatly we are not able to provide you with the amount you want", "Oops!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        con.Close(); 
    }

标签: c#visual-studio

解决方案


您的代码存在许多问题:

  • 您的主要问题:不从第一个命令中处理阅读器对象
  • 出于同样的原因,您还在连接仍处于打开状态时使用消息框阻止线程
  • 您将用户输入直接插入到查询中,这使您容易受到注入攻击和语法错误的影响。确保您不这样做的一个好方法是将批次存储在const string
  • 您的更新查询还有额外的'引号,它们是语法错误
  • productid不是字符串,在这种情况下,无论如何您都不应该将其括在引号中
  • 如果你int从读者那里得到一个结果,你不应该把它字符串化,然后再次解析它int.Parse(dr.GetValue(0).ToString()),而不是转换它(int) dr.GetValue(0)(你可能还想检查一下DBNull
  • 如果结果中只有一行和一列,则可以使用ExecuteScalar
  • 您可以将这两个查询合并为一个,并为自己节省两批的往返行程
  • 您在代码中嵌入了连接字符串,它应该保存在设置文件中
    private void button2_Click(object sender, EventArgs e) // PLACING ORDERS
    {
        int rowcount;
        const string query = @"
UPDATE Production.ProductInventory
SET Quantity -= @qty
WHERE ProductId = @productId
  AND Quantity >= @qty;
";
        using (SqlConnection con = new SqlConnection(Properties.Settings.ConnectionString))
        using (SqlCommand cmd1 = new SqlCommand(query,con))
        {
            cmd1.Parameters.Add("@productId", SqlDbType.Int).Value = int.Parse(textBox1.Text);
            cmd1.Parameters.Add("@qty", SqlDbType.Int).Value = qty;

            con.Open();
            rowcount = cmd.ExecuteNonQuery();
        }
        if(rowcount == 0)
        {
            MessageBox.Show("Unfortunately we are not able to provide you with the amount you want", "Oops!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }

推荐阅读