我正在为一个名为OTServer的游戏服务器编写数据库管理器,我第二次使用executereader()时遇到了问题。这是代码:
private void button1_Click(object sender, EventArgs e)
{
Form1 f = new Form1();
MySqlConnection conn = new MySqlConnection();
conn.ConnectionString = "Server=" + f.GetText1().Text + ";Username=" + f.GetText2().Text + ";Pwd=" + f.GetText3().Text + ";Database=" + f.GetText4().Text + ";";
conn.Open();
MySqlCommand cmd = new MySqlCommand("SELECT * FROM `players` WHERE name = @Name", conn);
cmd.Parameters.AddWithValue("@Name", textBox1.Text);
MySqlDataReader Reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (Reader.Read())
{
label7.Text = (string)Reader[1];
label7.Show();
label8.Text = Reader[5].ToString();
label8.Show();
if ((int)Reader[6] == 1)
{
label9.Text = "Sorcerer (1)";
}
if ((int)Reader[6] == 2)
{
label9.Text = "Druid (2)";
}
if ((int)Reader[6] == 3)
{
label9.Text = "Paladin (3)";
}
if ((int)Reader[6] == 4)
{
label9.Text = "Knight (4)";
}
if ((int)Reader[6] == 0)
{
label9.Text = "None (0)";
}
label9.Show();
if ((int)Reader[3] == 1)
{
label10.Text = "Player";
}
if ((int)Reader[3] == 2)
{
label10.Text = "Tutor";
}
if ((int)Reader[3] == 3)
{
label10.Text = "Senior Tutor";
}
if ((int)Reader[3] == 4)
{
label10.Text = "Gamemaster";
}
if ((int)Reader[3] == 5)
{
label10.Text = "Community Manager";
}
if ((int)Reader[3] == 6)
{
label10.Text = "God";
}
if ((int)Reader[3] < 1 || (int)Reader[3] > 6)
{
label10.Text = "Unknown";
}
label10.Show();
label13.Text = "Account: " + Reader[4].ToString();
label13.Show();
}
Reader.Close();
cmd = new MySqlCommand("SELECT * FROM accounts WHERE id = @Account_ID", conn);
cmd.Parameters.AddWithValue("@Account_ID", label13.Text);
Reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (Reader.Read())
{
label11.Text = (string)Reader[0];
label11.Show();
}
Reader.Close();
}
答案 0 :(得分:3)
建议的解决方案:尝试在using
周围加DataReader
块,或在其上调用Dispose
:
using (DataReader Reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
// ...do something with your data reader... then finish by:
Reader.Close();
} // <-- Reader.Dispose() called automatically at the end of using block.
// ...prepare second command...
// the same again for the second command:
using (DataReader Reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
// ...
Reader.Close();
}
您的问题的假设原因:数据库连接对象可能会进行一些内部簿记以跟踪数据读取器。我发现在一个类似的场景中,你一次只允许一个DataReader
。因此,我认为您的代码存在的问题是,Close
Reader
时,您没有明确Dispose
,因此连接对象认为第一个数据读取器仍在在执行第二个时使用。
除了...... 为什么不简化这段代码:
if ((int)Reader[6] == 1)
{
label9.Text = "Sorcerer (1)";
}
if ((int)Reader[6] == 2)
{
label9.Text = "Druid (2)";
}
...
到switch
声明?:
int x = (int)(Reader[6]);
string label9Text = string.Empty;
switch (x)
{
case 1: label9Text = "Sorcerer (1)"; break;
case 2: label9Text = "Druid (2)"; break;
...
}
label9.Text = label9Text;
(这样可以省去相当多的重复输入。)
答案 1 :(得分:2)
好吧,假设您的代码是正确的,那么在您的代码中显示时,执行两个读者时应该没有问题。也许你有问题,因为没有处理命令或其他东西。我推荐这样的方法(使用Northwind db进行的示例):
using (SqlConnection connection = new SqlConnection("Data Source=.\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI;"))
{
connection.Open();
using (SqlCommand command = new SqlCommand("SELECT * FROM Orders", connection))
{
using (SqlDataReader reader = command.ExecuteReader(System.Data.CommandBehavior.SingleRow))
{
while (reader.Read())
{
Console.WriteLine(reader.GetString(2));
}
}
}
using (SqlCommand command = new SqlCommand("SELECT * FROM Products", connection))
{
using (SqlDataReader reader = command.ExecuteReader(System.Data.CommandBehavior.SingleRow))
{
while (reader.Read())
{
Console.WriteLine(reader.GetString(1));
}
}
}
}
在识别播放器类型时,您应该清理代码。改为创建一个枚举:
public enum PlayerType
{
None = 0,
Sorcerer = 1,
Druid = 2,
Paladin = 3
}
然后在阅读时执行以下操作:
PlayerType playerType = (PlayerType)reader.GetInt32(6);
label9.Text = playerType.ToString();