简体   繁体   English

关闭MySql数据读取器连接

[英]Closing MySql datareader connection

So this is a little bit code-ceptionlike. 因此,这有点像代码接收。

I have a function that is checking the last ID in a table, this function is called within another function. 我有一个检查表中最后一个ID的函数,该函数在另一个函数中调用。 At the end of that function, I have another function that's opening another datareader. 在该函数的结尾,我有另一个函数正在打开另一个数据读取器。

Error: 错误:

There is already an open Datareader associated with this connection which must be closed first. 已经有一个与此连接相关联的打开的Datareader,必须首先关闭它。

getLastIdfromDB() 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;
}

This function is later-on used in this function: 此函数稍后在此函数中使用:

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();
                }
        }
}

What would be the best way for me to solve this problem and in the future be sure to close my connections properly? 对我来说,解决此问题的最佳方法是什么?将来一定要正确关闭我的连接吗?

UPDATE: (per request, included DB_connect) 更新:(每个请求,包括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();
        }
    }
}

You are trying to have multiple open readers on the same connection. 您试图在同一连接上有多个打开的阅读器。 This is commonly called "MARS" (multiple active result sets). 这通常称为“ MARS”(多个活动结果集)。 MySql seems to have no support for it. MySql似乎不支持它。

You will have to either limit yourself to one open reader at a time, or use more than one connection, so you can have one connection for each reader. 您将不得不一次只限制一个打开的阅读器,或者使用多个连接,因此每个阅读器可以有一个连接。

My suggestion would be to throw away that singleton-like thingy and instead use connection pooling and proper using blocks. 我的建议是扔掉类似单例的东西,而使用连接池和适当的using块。

As suggested by Pikoh in the comments, using the using clause indeed solved it for me. 正如Pikoh在评论中所建议的Pikoh ,使用using子句确实为我解决了它。

Working code-snippet: 工作代码段:

getLastIdFromDB getLastIdFromDB

using (MySqlDataReader reader2 = cmd2.ExecuteReader()) { 

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

Your connection handling here is not good. 您的连接处理在这里不好。 You need to ditch the DB_connect . 您需要DB_connect No need to maintain a single connection - just open and close the connection each time you need it. 无需维护单个连接-每次需要时只需打开和关闭连接即可。 Under the covers, ADO.NET will "pool" the connection for you, so that you don't actually have to wait to reconnect. 在幕后,ADO.NET将为您“合并”连接,因此您实际上不必等待重新连接。

For any object that implements IDisposable you need to either call .Dispose() on it in a finally block, or wrap it in a using statement. 对于任何实现IDisposable的对象,您需要在finally块中对其调用.Dispose()或将其包装在using语句中。 That ensures your resources are properly disposed of. 这样可以确保正确处理您的资源。 I recommend the using statement, because it helps keep the scope clear. 我建议using语句,因为它有助于保持范围清晰。

Your naming conventions should conform to C# standards. 您的命名约定应符合C#标准。 Methods that return a boolean should be like IsConnected , not IsConnect . 返回布尔值的方法应该类似于IsConnected ,而不是IsConnect addPlayerBtn_Click should be AddPlayerButton_Click . addPlayerBtn_Click应该是AddPlayerButton_Click getLastIdFromDB should be GetlastIdFromDb or getLastIdFromDatabase . getLastIdFromDB应该是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;
}

Note, your query is bad too. 注意,您的查询也很糟糕。 I suspect you're using a string data type instead of a number, even though your ID's are number based. 我怀疑您使用的是字符串数据类型而不是数字,即使您的ID是基于数字的。 You should switch your column to a number data type, then select the max() number. 您应该将列切换为数字数据类型,然后选择max()数字。 Or use an autoincrementing column or sequence to get the next ID. 或使用自动递增的列或序列来获取下一个ID。 Reading every single row to determine the next ID and incrementing a counter not good. 读取每一行以确定下一个ID并增加计数器效果不好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM