多次使用SqlCommand时出错

时间:2014-05-08 19:54:43

标签: sql database visual-studio-2012

我正在使用SqlCommand函数executeNONQuery(),但它给了我一个错误: 已经有一个与此命令关联的打开的datareader必须先关闭 我知道我需要关闭它。所以我使用了dispode方法,但它没有用。 有人可以帮帮我吗? 谢谢!

这里有一些代码:

                    Product pr = new Product();
                    pr.command.Dispose();
                    if ((t=(search(int.Parse(CatNum.Text))))!=null)
                    {
                        if (t == "Float")
                        {                            
                            pr.command.Dispose();
                            pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
                            SqlDataReader reader = pr.command.ExecuteReader();
                            float currAmount = 0;
                            while (reader.Read())
                            {
                                currAmount = float.Parse(reader["amount"].ToString());
                            }

                            pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), float.Parse(Amount.Text) + currAmount);                            
                            pr.command.ExecuteNonQuery();

                            CatNum.Text = string.Empty;
                            CatNum.Focus();
                            sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
                        }
                        else if (int.TryParse(Amount.Text, out q) && t == "Integer")
                        {                           
                            pr.command.Dispose();
                            pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
                            SqlDataReader reader = pr.command.ExecuteReader();
                            int currAmount = 0;
                            while (reader.Read())
                            {
                                currAmount = int.Parse(reader["amount"].ToString());
                            }

                            pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), int.Parse(Amount.Text) + currAmount);
                            pr.command.ExecuteNonQuery();

                            CatNum.Text = string.Empty;
                            CatNum.Focus();
                            sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
                        }

3 个答案:

答案 0 :(得分:0)

在开始第二次查询之前添加此项。

reader.Close();

答案 1 :(得分:0)

您应该使用try-catch-finally异常管理,以避免对代码进行未处理的异常。

如果命令失败,或者因为连接丢失或仅仅因为查询不正确,读者将不会关闭,因为它不会到达代码的那一部分。

尝试按照以下方式输入代码:

    Product pr = new Product();
             try {
                    pr.command.Dispose();
                    if ((t=(search(int.Parse(CatNum.Text))))!=null)
                    {
                        if (t == "Float")
                        {                            
                            pr.command.Dispose();
                            pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
                            SqlDataReader reader = pr.command.ExecuteReader();
                            float currAmount = 0;
                            while (reader.Read())
                            {
                                currAmount = float.Parse(reader["amount"].ToString());
                            }
                            reader.close;
                            pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), float.Parse(Amount.Text) + currAmount);                            
                            pr.command.ExecuteNonQuery();

                            CatNum.Text = string.Empty;
                            CatNum.Focus();
                            sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
                        }
                        else if (int.TryParse(Amount.Text, out q) && t == "Integer")
                        {                           
                            pr.command.Dispose();
                            pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
                            SqlDataReader reader = pr.command.ExecuteReader();
                            int currAmount = 0;
                            while (reader.Read())
                            {
                                currAmount = int.Parse(reader["amount"].ToString());
                            }
                            reader.close;
                            pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), int.Parse(Amount.Text) + currAmount);
                            pr.command.ExecuteNonQuery();

                            CatNum.Text = string.Empty;
                            CatNum.Focus();
                            sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
                        }
}
         catch (SqlException sqlex) {
             // do your thing when sql exception pops out }
         catch (Exception ex) {
             // do your thing when any exception pops out }
         finally {
          reader.close; }

即使出现异常,也会关闭阅读器。

答案 2 :(得分:0)

这段代码有很多问题,我真的不知道从哪里开始。

没有让任何事情变得复杂并保持尽可能通用我建议废弃你的产品类,它看起来像你的SqlCommand的持有者,并且根据你的用法,这甚至不是很有帮助,甚至没有考虑到问题用这种方法。

每次使用新的SqlCommand和连接会好得多,实际上并没有那么多代码:

using (var connection = new SqlConnection("YourConnectionString"))
using (var command = new SqlCommand("CommandText", connection))
{
    connection.Open();
    // User your command here
}

接下来不要使用string.Format来构建查询,使用正确的参数化查询,您将受益于类型安全和查询计划缓存,以及消除SQL注入的风险。

所以而不是

command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));

你会使用:

command.CommandText = "SELECT Amount FROM Storage WHERE CatalogNumber = @CatalogNumber";
int catNum = 0;
if (!int.TryParse(CatNum.Text, out catNum))
{
    // Do something to handle an invalid input
}
command.Parameters.AddWithValue("@CatalogNumber", catNum);

下一个问题是:

while (reader.Read())
{
    currAmount = float.Parse(reader["amount"].ToString());
}

这里有两个问题,第一个是不必要的转换(你可以只使用reader.GetFloat(),但更重要的是你只会迭代整个数据集,以便将最后一行的值赋给你的变量。你的数据集只有一行,那么这不是一个真正的问题,但你也可以使用ExecuteScalar获得一个值。

currAmount = float.Parse(command.ExecuteScalar().ToString());

最后,您实际上并未在此更新中执行任何操作:

Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}

您刚刚从同一张表中读过amount,而SET CatalogNumber = 1 WHERE CatalogNumber = 1什么也没做。

我无法确定你为什么要在两个独立的块中处理浮点数和整数,但看起来你的代码可以缩减为:

int catNum = 0;
if (!int.TryParse(CatNum.Text, out catNum))
{
    // Do something to handle an invalid input
}
float currAmount = 0;
using (var connection = new SqlConnection("YourConnectionString"))
using (var command = new SqlCommand("SELECT Amount FROM Storage WHERE CatalogNumber = @CatalogNumber", connection))
{
    command.Parameters.AddWithValue("@CatalogNumber", catNum);
    connection.Open();
    currAmount = float.Parse(command.ExecuteScalar().ToString());
}

CatNum.Text = string.Empty;
CatNum.Focus();
sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");