[英]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
应该是GetlastIdFromDb
或getLastIdFromDatabase
。
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.