InvalidOpearationException:已经有一个打开的DataReader

时间:2013-10-08 08:02:54

标签: c# .net sql sql-server winforms

您好我通过以下代码从SQL创建控件:

string query = "SELECT * FROM [schema] WHERE idSch=@id";
            SqlCommand com = new SqlCommand(query, con);
            com.Parameters.AddWithValue("@id", result);
            con.Open();
            SqlDataReader read= com.ExecuteReader();

            while (read.Read())
            {

                createLabelCmd((int)read["x"], (int)read["y"]);


            }
            con.Close();

问题是createLabelCmd包含SqlCommand,需要开放SqlConnection

内部createLabelCmd

String ResultSitting
private void createLabelCmd(int x, int y)
    {
for (int i = 0; i < 1; i++)
        {
            var newLabel = new Label();
            newLabel.Location = new Point(x, y);
            newLabel.Text = realpocsed.ToString();
            string sitting = newLabel.Name;
            string sittingSearch = (sitting).Substring(3, 1);
            if (sittingSearch != null && kzajezdu == "kZajezdu")
            {
                string querySitting = "SELECT name, surname FROM klient WHERE sitting = @sitting AND event=@event AND year=@year";
                SqlCommand cmdSitting = new SqlCommand(querySitting, spojeni);
                cmdSitting.Parameters.AddWithValue("@sitting", sittingSearch);
                cmdSitting.Parameters.AddWithValue("@event", idEvent);
                cmdSitting.Parameters.AddWithValue("@year", klientClass.Year());

                ResultSitting = cmdSitting.ExecuteScalar().ToString().Trim(); //This might be the issue

            }

            if (kzajezdu == "kZajezdu")
            {
                newLabel.MouseHover += delegate(object sender, EventArgs e)
                {
                    ToolTip ToolTip1 = new ToolTip();
                    ToolTip1.ShowAlways = true;
                    if (sittingSearch != null)
                    {
                        ToolTip1.Show(ResultSitting, newLabel);
                    }
                    else { ToolTip1.Show("This sitting is Empty!", newLabel); }
                };

            }

            panel1.Controls.Add(newLabel);
        }

我得到一个例外:InvalidOpearationException: There is already an open DataReader associated with this Command which must be closed first.

请你帮我解决一下?

编辑为SonerGönül建议:

try
        {
            string query = "SELECT * FROM [schema] WHERE idSch=@id";
            SqlCommand com = new SqlCommand(query, con);
            com.Parameters.AddWithValue("@id", idSch);
            con.Open();
            SqlDataReader read= com.ExecuteReader();

            while (precti.Read())
            {
                createLabelCmd((int)read["x"], (int)read["y"]);

            }
            con.Close();
        }

5 个答案:

答案 0 :(得分:2)

因为当您使用打开的SqlDataReader进行循环时,已经有一个打开的连接。

来自DataReaders (ADO.NET)

  

“您可以使用ADO.NET DataReader检索只读,   来自数据库的仅向前流数据。

     

结果在查询执行时返回,并存储在   客户端上的网络缓冲区,直到您使用Read请求它们   DataReader的方法“

作为一般推荐,请使用using之类的;

using(SqlDataReader read= com.ExecuteReader())
{
    while (read.Read())
    {
       createLabelCmd((int)read["x"], (int)read["y"]);
    }
}

或者在连接字符串中设置它;

...MultipleActiveResultSets=true;

答案 1 :(得分:2)

问题的原因在其他答案中有所概述(当DataReader打开时,该读取器使用的连接无法提供其他命令),但很多人都没有谈到为此类引入的MultipleActiveResultSets情况

只需更改连接字符串即可包含此选项,您的代码无需任何更改即可运行

Server=yourServer;Database=yourDB;Trusted_Connection=True;MultipleActiveResultSets=true;

要完成答案,可以从SQL Server 2005和there are minor problems开始提供MARS,您应该知道。

答案 2 :(得分:1)

我猜你正在写一个坐姿计划器并尝试在特定位置展示标签。因此,您最好从klient表中选择给定事件的所有记录,并将它们放在DataSet中。然后迭代它(使用foreach)并创建标签。这样,只有一个命令应该发送到数据库,显然,应用程序的性能会更好。

话虽如此,我不明白你的sittingSearch变量是如何工作的,我认为它需要修改。

答案 3 :(得分:1)

您可以在createLabelCmd中使用第二个连接,也可以在初始连接中启用MARS(多个活动结果集),方法是在连接字符串中添加“MultipleActiveResultSets = True”。

http://msdn.microsoft.com/en-us/library/h32h3abf.aspx

答案 4 :(得分:0)

将MARS设置为True AND 确保我使用ToList();在我的if语句和返回中 在下面的代码中,我在if语句的两个条件中都缺少toList(),我在发布后在IIS 8.5上收到错误。将语句更新到下面工作的@!

var varM = (id == 1) ? db.M.Where(x => x.UN== userID).ToList() : db.M.Where(x => x.EUN== userID).ToList();