关闭MySql datareader连接

时间:2017-02-22 15:23:25

标签: c# mysql ado.net

所以这有点像代码一样。

我有一个函数正在检查表中的最后一个ID,这个函数在另一个函数中调用。在该功能结束时,我有另一个功能,即打开另一个数据头。

错误:

  

已经有一个与此连接关联的打开的Datareader必须先关闭。

getLastIdfromDB()

public string getLastIdFromDB()
{
     int lastIndex;
     string lastID ="";
     var dbCon = DB_connect.Instance();

     if (dbCon.IsConnect())
     {
         MySqlCommand cmd2 = new MySqlCommand("SELECT ID FROM `competitor`", dbCon.Connection);

         try
         {
             MySqlDataReader reader = cmd2.ExecuteReader();

             while (reader.Read())
             {
                   string item = reader2["ID"].ToString();
                   lastIndex = int.Parse(item);
                   lastIndex++;
                   lastID = lastIndex.ToString();
              }
         }
         catch (Exception ex)
         {
              MessageBox.Show("Error:" + ex.Message);
         }
     }

     return lastID;
}

此功能稍后在此功能中使用:

private void addPlayerBtn_Click(object sender, EventArgs e)
{
     ListViewItem lvi = new ListViewItem(getLastIdFromDB());
     .........................................^ 
     ...                                    HERE
     ...
     ...   irrelevant code removed
     .........................................

            var dbCon = DB_connect.Instance();

            if (dbCon.IsConnect())
            {
                MySqlCommand cmd = new MySqlCommand("INSERT INTO `competitor`(`ID`, `Name`, `Age`) VALUES(@idSql,@NameSql,@AgeSql)", dbCon.Connection);
                cmd.Parameters.AddWithValue("@idSql", getLastIdFromDB());
                cmd.Parameters.AddWithValue("@NameSql", playerName.Text);
                cmd.Parameters.AddWithValue("@AgeSql", playerAge.Text);

                try
                {
                    cmd.ExecuteNonQuery();
                    listView1.Items.Clear();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error:" + ex.Message);
                    dbCon.Connection.Close();
                }
                finally 
                { 
                    updateListView();
                }
        }
}

对我来说,解决这个问题的最佳方式是什么,将来一定要正确关闭我的连接?

更新:(每个请求,包括DB_connect)

    class DB_connect
    {
        private DB_connect()
        {
        }

        private string databaseName = "simhopp";

        public string DatabaseName
        {
            get { return databaseName; }
            set { databaseName = value; }
        }

        public string Password { get; set; }
        private MySqlConnection connection = null;

        public MySqlConnection Connection
        {
            get { return connection; }
        }

        private static DB_connect _instance = null;

        public static DB_connect Instance()
        {
            if (_instance == null)
                _instance = new DB_connect();
            return _instance;
        }

        public bool IsConnect()
        {
            bool result = true;

            try
            {
                if (Connection == null)
                {
                    if (String.IsNullOrEmpty(databaseName))
                        result = false;

                    string connstring = string.Format("Server=localhost; database={0}; UID=root;", databaseName);

                    connection = new MySqlConnection(connstring);
                    connection.Open();

                    result = true;
                }
            }
            catch (Exception ex)
            {
                Console.Write("Error: " + ex.Message);
            }

            return result;
        }

        public void Close()
        {
            connection.Close();
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您正尝试在同一连接上安装多个打开的阅读器。这通常被称为" MARS" (多个活动结果集)。 MySql似乎不支持它。

您必须一次限制一个打开的阅读器,或使用多个连接,这样您就可以为每个阅读器建立一个连接。

我的建议是抛弃那些类似单身的东西,而是使用connection pooling和正确的using块。

答案 1 :(得分:0)

这里的连接处理不好。你需要放弃DB_connect。无需维护单个连接 - 只需在每次需要时打开和关闭连接。在幕后,ADO.NET将" pool"你的联系,所以你实际上不必等待重新连接。

对于任何实现IDisposable的对象,您需要在.Dispose()块中调用finally,或将其包装在using语句中。这可确保您的资源得到妥善处理。我建议使用using语句,因为它有助于保持范围清晰。

您的命名约定应符合C#标准。返回布尔值的方法应该类似于IsConnected,而不是IsConnectaddPlayerBtn_Click应为AddPlayerButton_ClickgetLastIdFromDB应为GetlastIdFromDbgetLastIdFromDatabase

public string GetLastIdFromDatabase()
{
     int lastIndex;
     string lastID ="";

     using (var connection = new MySqlConnection(Configuration.ConnectionString))
     using (var command = new MySqlCommand("query", connection))
     {
         connection.Open();
         MySqlDataReader reader = cmd2.ExecuteReader();

         while (reader.Read())
         {
               string item = reader2["ID"].ToString();
               lastIndex = int.Parse(item);
               lastIndex++;
               lastID = lastIndex.ToString();
         }   
     }

     return lastID;
}

注意,您的查询也很糟糕。我怀疑您使用字符串数据类型而不是数字,即使您的ID是基于数字的。您应该将列切换为数字数据类型,然后选择max()数字。或使用自动增量列或序列来获取下一个ID。读取每一行以确定下一个ID并使计数器递增不好。