MySql.Data.MySqlClient.MySqlException:'已经有一个与此Connection关联的打开DataReader,必须先关闭它。

时间:2018-06-01 20:35:57

标签: c# mysql

MySqlCommand Sql1 = new MySqlCommand("SELECT * FROM animal WHERE idAnimal ='" + label1.Text + "'", Connection);

MySqlDataReader dr1;
dr1 = Sql1.ExecuteReader();

while (dr1.Read())
{
    String idAnimal = dr1["idAnimal"].ToString();

    MySqlCommand Sql2 = new MySqlCommand("SELECT * FROM town WHERE id ='" + idAnimal + "'", Connectio);
    MySqlDataReader dr2;
    dr2 = Sql2.ExecuteReader();

    while (dr2.Read())
    {
        dataGridView1.Rows.Add(dr2["number"], dr2["name"]);
    }

    dr2.Close();
}

dr1.Close();
Connection.Close();

3 个答案:

答案 0 :(得分:2)

解决此问题的最佳方法是使用 JOIN (并修复 HUGE sql注入漏洞,而我们正在使用它):

string sql = "SELECT t.number, t.name FROM animal a INNER JOIN town t ON t.ID = a.idAnimal WHERE a.idAnimal= @idAnimal";

using (var cn = new MySqlConnection("connection string here"))
using (var cmd = new MySqlCommand(sql, cn))
{
    cmd.Parameters.Add("@idAnimal", MySqlDbType.Int32).Value = int.Parse(label1.Text);

    cn.Open();
    using (var dr = cmd.ExecuteReader())
    {
        while(dr.Read())
        {
            dataGridView1.Rows.Add(dr["number"], dr["name"]);
        }
        dr.Close();
    }
}

此外,您应该查看数据绑定以将这些结果连接到网格,而不是手动添加行。那会让你编写这样的代码:

string sql = "SELECT t.number, t.name FROM animal a INNER JOIN town t ON t.ID = a.idAnimal WHERE a.idAnimal= @idAnimal";
using (var cn = new MySqlConnection("connection string here"))
using (var cmd = new MySqlCommand(sql, cn))
{
    cmd.Parameters.Add("@idAnimal", MySqlDbType.Int32).Value = int.Parse(label1.Text);
    cn.Open();
    using (var dr = cmd.ExecuteReader())
    {
        dataGridView1.DataSource = dr;
        dr.Close();
    }
}

但是如果真的想要知道如何将两个DataReader一起激活,那么可以通过拥有两个连接对象来实现:

using (var cn1 = new MySqlConnection("connection string here"))
using (var sql1 = new MySqlCommand("SELECT * FROM animal WHERE idAnimal = @idAnimal", cn1))
{
    sql1.Parameters.Add("@idAnimal", MySqlDbType.Int32).Value = int.Parse(label1.Text);
    cn1.Open();
    using (var dr1 = sql1.ExecuteReader())
    {    
        while (dr1.Read())
        {
            String idAnimal = dr1["idAnimal"].ToString();

            using (var cn2 = new MySqlConnection("connection string here"))
            using (var sql2 = new MySqlCommand("SELECT * FROM town WHERE id = @idAnimal", cn2))
            {
                cn2.Parameters.Add("@idAnimal", MySqlDbType.Int32).Value = int.Parse(idAnimal);
                cn2.Open();
                using(var dr2 = sql2.ExecuteReader())
                {
                    while (dr2.Read())
                    {
                        dataGridView1.Rows.Add(dr2["number"], dr2["name"]);
                    }
                    dr2.Close();
                }
            }
        }
        dr1.Close();
    }
}

但请注意,这是JOIN + DataBinding选项的两倍多。

另请注意,ADO.Net提供程序中的糟糕的做法可以保留一个数据库连接以便在您的应用程序中重复使用。除了限制您同时使用多个数据库查询的能力之外,正如我们在此处所看到的,ADO.Net使用名为Connection Pooling的功能,并且重新使用相同的连接对象会干扰此问题。在大多数情况下,创建新连接对象确实更好,只需重新使用连接字符串。

答案 1 :(得分:0)

你不能使用相同的"连接"同时在两个命令中变量。如果要在第一个读取内部打开另一个连接,则必须创建第二个连接。

答案 2 :(得分:0)

对于DataReader和ExecuteNonQuery使用相同的连接,根据MSDN,不支持ExecuteNonQuery。您必须为每个datareader创建sperate连接