【问题标题】:MySQL ADO.Net Nested DataReadersMySQL ADO.Net 嵌套数据读取器
【发布时间】:2018-07-03 23:52:47
【问题描述】:

我想用一条 SQL 语句检索帐户列表,然后在运行更多 SQL 语句时循环它们。当我尝试时,我收到此错误:

未处理的异常:MySql.Data.MySqlClient.MySqlException:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭。

这是一个例子:

using (MySqlConnection connection = new MySqlConnection("host=..."))
{

    connection.Open();

    using (MySqlCommand cmdAccounts = connection.CreateCommand())
    {

        cmdAccounts.CommandText = "SELECT id, name FROM accounts";

        using (MySqlDataReader accounts = cmdAccounts.ExecuteReader())
        {

            while (accounts.Read())
            {

                Console.WriteLine("Account {0}:", account.GetString("name"));

                using (MySqlCommand cmdPictures = connection.CreateCommand())
                {

                    cmdPictures.CommandText = "SELECT id, width, height FROM pictures WHERE account_id = @accountId";
                    cmdPictures.Parameters.AddWithValue("@accountId", accounts.GetInt32("id"));

                    using (MySqlDataReader pictures = cmdPictures.ExecuteReader())
                    {

                        while (pictures.Read())
                        {
                            Console.WriteLine("\tPicture #{0}: {1} x {2}", pictures.GetInt32("id"), picture2.GetInt32("width"), picture2.GetInt32("height"));
                        }

                    }
                }
            }
        }
    }
}

我是否必须使用 DataSet,或者有没有办法在 MySQL 中仅使用 DataReaders 来做到这一点?

【问题讨论】:

  • 您需要使用两个连接并将两个命令链接到两个连接。据我所知,MySql 在其连接字符串键中没有 MultipleActiveResultSets 选项。

标签: c# mysql nested ado.net datareader


【解决方案1】:

您可以使用 DataReaders 执行此操作,但您需要为两个级别的阅读器使用单独的连接对象:

using (MySqlConnection connection = new MySqlConnection("host=..."))
using (MySqlCommand cmdAccounts = MySqlCommand("SELECT id, name FROM accounts" , connection))
{
    connection.Open();

    using (MySqlConnection connection2 = new MySqlConnection("host=..."))
    using (MySqlCommand cmdPictures = new MySqlCommand("SELECT id, width, height FROM pictures WHERE account_id = @accountId", connection2))
    using (MySqlDataReader accounts = cmdAccounts.ExecuteReader())
    {
        cmdPictures.Parameters.Add("@accountId", MySqlDbType.Int32); 
        connection2.Open()

        while (accounts.Read())
        {    
            Console.WriteLine("Account {0}:", account.getString("name"));

            cmdPictures.Parameters["@accountId"].Value = accounts.GetInt32("id");

            using (MySqlDataReader pictures = cmdPictures.ExecuteReader())
            {
                while (pictures.Read())
                {
                    Console.WriteLine("\tPicture #{0}: {1} x {2}", pictures.GetInt32("id"), picture2.GetInt32("width"), picture2.GetInt32("height"));
                }
            }
        }
    }
}

但即使这样更好,但首先考虑问题的方式仍然是错误的。你真的想JOIN数据库中的两个表:

string sql = 
    "SELECT a.id as AccountID, a.name, p.id as PictureID, p.width, p.height" + 
    " FROM accounts a" +
    " INNER JOIN pictures p on p.account_id = a.id" +
    " ORDER BY a.name, a.id";

using (var cn = new MySqlConnection("host=..."))
using (var cmd = new MySqlCommand(sql, cn))
{
    cn.Open();
    using (var rdr = cmd.ExecuteReader())
    {
        bool reading = rdr.Read();
        while (reading)
        {
            int CurrentAccount = rdr.GetInt32("AccountId");
            Console.WriteLine("Account {0}:", rdr.GetString("name"));

            while (reading && CurrentAccount == rdr.GetInt32("AccountId"))
            {
               Console.WriteLine("\tPicture #{0}: {1} x {2}", 
                 rdr.GetInt32("PictureId"), rdr.GetInt32("width"), rdr.GetInt32("height"));
               reading = rdr.Read();
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    为什么不使用 SqlDataAdapter 填充数据表? 然后,foreach 数据表中的行,提取第二个 sql 命令并显示日期? 只是一个初学者的意见,尝试一下或查看更多答案

    【讨论】:

      猜你喜欢
      • 2011-01-26
      • 2012-06-24
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 2021-04-29
      相关资源
      最近更新 更多