是否可以使用 ExecuteReader() 两次?

发布于 2024-10-03 18:48:27 字数 2755 浏览 3 评论 0原文

我正在为名为 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();
    }

I'm programming a database manager for a gameserver called OTServer, and I'm having problems using executereader() the second time. Here's code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深陷 2024-10-10 18:48:27

建议的解决方案:尝试在 DataReader 周围放置一个 using 块,或对其调用 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。所以我相信您的代码的问题在于,当您关闭 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;

:(这会节省您大量的重复输入。)

Suggested solution: Try putting a using block around your DataReader, or call Dispose on it:

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

Assumed cause of your problem: The DB connection object may do some internal book-keeping to keep track of data readers. I've found out in a similar scenario that you're only allowed one DataReader at a time. So I believe the problem with your code is that, while you Close the Reader, you haven't explicitly Disposed it, so the connection object thinks the first data reader is still in use when you execute the second one.


Besides... why not simplify this code:

        if ((int)Reader[6] == 1)
        {
            label9.Text = "Sorcerer (1)";
        }
        if ((int)Reader[6] == 2)
        {
            label9.Text = "Druid (2)";
        }
        ...

to a switch statement?:

        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;

(That would save you quite a bit of repetitive typing.)

夕色琉璃 2024-10-10 18:48:27

好吧,假设您的代码是正确的,您在执行代码中显示的两个读取器时应该不会有问题。也许你因为没有处理命令或其他原因而遇到问题。我推荐这样的方法(使用 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();

Well, assuming that your code is correct you shouldn't have problem in executing two readers as you show in your code. Maybe you have problems because of not disposing commands or something else. I recommend an approach like this (Example made with 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));
                    }
                }
            }
        }

You should clean your code when recognizing the type of player. Create an enum instead:

public enum PlayerType
{
    None = 0,
    Sorcerer = 1,
    Druid = 2,
    Paladin = 3
}

And then do the following while reading:

PlayerType playerType = (PlayerType)reader.GetInt32(6);
label9.Text = playerType.ToString();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文