2010-11-21 5 views
1

Je suis en train de programmer un gestionnaire de base de données pour un serveur de jeu appelé OTServer, et j'ai des problèmes pour utiliser executereader() la deuxième fois. Voici le code:Est-il possible d'utiliser ExecuteReader() deux fois?

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

Quel genre de problèmes? De toute façon essayer de disposer de la commande aussi. –

Répondre

2

solution proposée: Essayez de mettre un bloc using autour de votre DataReader, ou appelez Dispose sur elle:

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

cause présumée de votre problème: L'objet de connexion DB peut faire de la comptabilité interne pour garder une trace des lecteurs de données. J'ai découvert dans un scénario similaire que vous êtes autorisé seulement un DataReader à la fois. Donc, je crois que le problème avec votre code est que, alors que Close le Reader, vous n'avez pas explicitement Dispose d, donc l'objet de connexion pense que le premier lecteur de données est toujours utilisé lorsque vous exécutez le second.


En plus ... pourquoi ne pas simplifier ce code:

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

à une déclaration 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; 

(Cela vous permettra d'économiser un peu de frappes répétées Eh bien, en supposant que votre code est correct yo,

1

Vous ne devriez pas avoir de problème à exécuter deux lecteurs comme vous le montrez dans votre code. Peut-être que vous avez des problèmes à cause de ne pas disposer de commandes ou d'autre chose. Je recommande une approche comme celui-ci (exemple faite avec 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)); 
        } 
       } 
      } 
     } 

Vous devez nettoyer votre code lors de la reconnaissance du type de joueur. Créer un ENUM à la place:

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

Et puis procédez comme suit lors de la lecture:

PlayerType playerType = (PlayerType)reader.GetInt32(6); 
label9.Text = playerType.ToString(); 
+1

suggère d'utiliser une table player_type, player_class etc .. vs une table –