【问题标题】:C# MySQL second DataReader in DataReader while loopC# MySQL 在 DataReader while 循环中的第二个 DataReader
【发布时间】:2012-08-11 07:09:46
【问题描述】:

正如您可能从标题中猜到的那样,我是否正在尝试这样做:

    #region check new nations
    private void checknewnations()
    {
        addtolog("server","Checking for new nations");
        string sql = "SELECT * FROM " + variables.tbl_nations + " WHERE nations_new=0";
        MySqlCommand cmd = new MySqlCommand(sql, connection);
        MySqlDataReader reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            addtolog("mysql",reader["nations_name"].ToString());

            int nation_ID = int.Parse(reader["nations_ID"].ToString());
            string nation_name = reader["nations_name"].ToString();
            string user_ID = reader["nations_user"].ToString();


            addnation(nation_ID, nation_name, user_ID);
        }
        addtolog("server","Finished checking for new nations.");
        //connection.Close();
        reader.Dispose();
    }
    #endregion

在while循环中调用它:

    #region addnation
    private void addnation(int nationIDnot, string nationName, string userID)
    {
        string nationID = makesixdigits(nationIDnot);
        string userName = "";

        string sql = "SELECT * FROM " + variables.tbl_users + " WHERE users_ID=" + userID;
        MySqlCommand cmd = new MySqlCommand(sql, connection);
        MySqlDataReader reader = cmd.ExecuteReader();


        while (reader.Read())
        {
            userName = reader["users_name"].ToString();
        }
        reader.Dispose();
        addtolog("add", "[" + nationID.ToString() + "] " + nationName + " [" + userID + "] " + userName);
    }
    #endregion

这在第二个代码块(在 while 循环中调用的那个)中给我一个错误,说已经有一个与连接关联的数据读取器。我该如何让它发挥作用,因为我确信有办法。

【问题讨论】:

    标签: c# mysql database connection datareader


    【解决方案1】:

    在循环中打开另一个连接,并使用它来获取第二个阅读器。 由于循环很紧凑,您可能更愿意在第一个方法中打开两个连接,将第二个传递给被调用的方法,然后在第一个(“外部”)方法结束时关闭它们。调用之间的时间应该足够短,尽快关闭连接的正常规则无关紧要。

    【讨论】:

    • 感谢您的回复 :) 我现在使用 2 个连接,虽然我在程序开始时打开它们并在程序结束时关闭它们,因为第一个 while 循环也是循环/timer_tick 的一部分,因此连接几乎经常被使用。
    • @user1599326 如果它是一个单线程控制台应用程序,符合“做数据库的东西,然后结束”(!)的丢失规范,那很好;无论如何,没有其他任何东西共享连接池。
    • 请记住,它属于弯曲规则的范畴,因为它只是一个做事不结束的小应用程序; “嘿,我们……的方式对可扩展性的影响是什么?” :)
    • 嗯,这个程序实际上是设计成一个持续运行的服务器程序(只连接MySql数据库,不直接连接客户端)
    • 在这种情况下,您真的想在方法开始时创建和打开连接,并在结束时关闭它们(最好使用using 确保这一点遇到异常时发生)。处理并发客户端连接的并发线程(如在服务器应用程序的客户端中)将具有单独的连接(否则您会在其中一个客户端中获得与上述相同的异常并且不知道为什么)并且池保持连接开销和总数据库连接数低于stackoverflow.com/a/3845924/400547
    【解决方案2】:

    DataReader 保持连接,直到它遍历所有记录。试试这个

    using(reader)
    {
       System.Data.DataTable dt = new System.Data.DataTable();
       dt.Load(reader);
    
       foreach(DataRow row in dt.Rows)
       {
            addtolog("mysql",row["nations_name"].ToString());
    
            int nation_ID = int.Parse(row["nations_ID"].ToString());
            string nation_name = row["nations_name"].ToString();
            string user_ID = row["nations_user"].ToString();
    
    
            addnation(nation_ID, nation_name, user_ID);
       }
    }
    

    这样两个阅读器就不会共享同一个连接

    【讨论】:

    • 会制作本地版本的表格吗?
    • 所有记录一次加载到dt,阅读器免费
    • 这种将 DataReader 结果集加载到 DataTable 中的方法对于我遇到的一些小型结果集场景来说看起来很方便。例如,顶级“客户/人员”行,然后有 0..n 个子行要循环,其中“n”通常是“少数”,即不是“千”。如果这些子行中的每一个都可能与多个其他表中的 0..n 个附加数据行相关,那么这种方法对于在不占用连接的情况下循环遍历这些第一级子行很有用。
    【解决方案3】:

    在 2008 年的连接字符串中,您可以通过 MultipleActiveResultSets=true; 获得多个活动结果集

    否则,只需建立另一个连接 - 不要重复使用相同的连接。

    【讨论】:

    • 非常感谢您的回答。这是一个显而易见且简单的解决方案:)
    • MARS 可以与 MySQL 一起使用吗?我认为它仍然特定于 SQLServer 2005 及更高版本。 (无论如何,我大多只是使用多个连接,除非我真的需要在同一个事务中通过交错调用来做一些事情)。
    • @JonHanna - 我不认为是这样,但是 MS 用户可以阅读这个问题,所以我涵盖了基础。
    • 好点。哦,海 MS 用户!在使用 MARS 之前阅读msdn.microsoft.com/en-us/library/h32h3abf%28v=vs.80%29.aspx
    • 我没有使用 mars 的东西,只是多个连接 :) 3 额外的代码行 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多