【问题标题】:Looping Through A ListViews Checked Items to Execute A Stored Procedure循环遍历 ListViews 检查项以执行存储过程
【发布时间】:2013-06-17 10:54:20
【问题描述】:

我拥有的是ListView,列表中的每个项目都有复选框。

单击按钮后,我会像这样收集我的“已检查项目”;

ListView.CheckedListViewItemCollection checkedItems = emps.CheckedItems;

            List<string> attend = new List<string>();

            foreach (ListViewItem item in checkedItems)
            {
                attend.Add(item.Text);
            }

我知道这是有效的,因为我打印了这样的内容;

string s = String.Join(",", attend); MessageBox.Show(s);

但是,我想使用这些 strings 并为列表中的每个字符串 (attend) 运行 SQL 存储过程。

像这样;

SqlConnection con = new SqlConnection(conn);
            con.Open();
            SqlCommand cmd = new SqlCommand("my_SP", con);
            cmd.CommandType = CommandType.StoredProcedure;

            foreach (string item in attend)
            {
                cmd.Parameters.Clear();
                cmd.Parameters.Add(new SqlParameter("@Name", item));
                cmd.Parameters.Add(new SqlParameter("@Course", attender.SelectedValue));
                cmd.ExecuteReader();
            }
            con.Close();

当我只检查列表中的一项时,这非常有效,当我检查多个项目时它会失败。

错误信息是;

There is already an open DataReader associated with this Command which must be closed first.

我已经尝试更改命令等的变量名称,但我没有看到 DataReader 在哪里打开,我之前没有遇到过这个错误。

【问题讨论】:

    标签: c# winforms stored-procedures


    【解决方案1】:

    打开连接时尝试以下方法

    使用 (SqlConnection conn = new SqlConnection()) { conn.Open(); Sqlmd.Connection = 连接; SqlDataAdapter da = new SqlDataAdapter(Sqlmd); //...ETC }

    【讨论】:

    • @Clev231,打开连接时,尤其是在循环时,请用“使用”附上您正在执行的操作,以便在准备好时处理所有内容。很高兴我能帮上忙。
    【解决方案2】:

    因为你在循环内部使用

    cmd.ExecuteReader();
    

    这个,首先循环打开一个 SqlDataReader(它未分配但它仍然存在),然后,当您重新执行循环时,未使用的 SqlDataReader 仍然阻塞连接。

    改为使用

    cmd.ExecuteNonQuery();
    

    确实应该在需要从数据库中读取数据的时候使用ExecuteReader,而不是需要进行插入、更新、删除操作的时候,所以你的代码应该这样改

        using(SqlConnection con = new SqlConnection(conn))
        using(SqlCommand cmd = new SqlCommand("my_SP", con))
        {
            con.Open();
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@Name", ""));
            cmd.Parameters.Add(new SqlParameter("@Course", ""));
            foreach (string item in attend)
            {
                cmd.Parameters["@Name"].Value = item;
                cmd.Parameters["@Course"].Value  = attender.SelectedValue);
                cmd.ExecuteNonQuery();
            }
         }
    

    也可以在循环外声明和添加参数,只改变循环内的值。这将提供更快的速度

    【讨论】:

    • 谢谢..帮助我理解了这个问题。
    • 您能向我解释一下接受的答案是如何解决您的问题的吗?我不明白,当然 using 语句是有益的,但错误消息应该仍然存在。
    • 是的,这让我明白我正在尝试重新打开我已多次声明的阅读器,这使我在下面得到了答案。但是我知道您的解决方案也可以,因此我投票赞成.
    【解决方案3】:

    感谢您的帮助,这让我觉得打开/关闭我的连接有问题。

    我是这样解决的;

    foreach (string item in attend)
                {
                    con.Open();
                    cmd.Parameters.Clear();
                    cmd.Parameters.Add(new SqlParameter("@Name", item));
                    cmd.Parameters.Add(new SqlParameter("@Course", attender.SelectedValue));
                    cmd.ExecuteReader();
                    con.Close();
                }
    

    虽然多次打开和关闭连接可能效率低下。

    【讨论】:

      【解决方案4】:

      试试下面的代码

      SqlConnection con = new SqlConnection(conn);
                  con.Open();
      
      
                  foreach (string item in attend)
                  {
                      cmd.Parameters.Clear();
                      cmd.Parameters.Add(new SqlParameter("@Name", item));
                      cmd.Parameters.Add(new SqlParameter("@Course", attender.SelectedValue));
                     SqlDataReader dtr = cmd.ExecuteReader();
       dtr.close();
                  }
                  con.Close();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多