2010-11-21 12 views
1

Ich programmiere einen Datenbankmanager für einen Gameserver namens OTServer, und ich habe Probleme mit executeReader() das zweite Mal. Hier Code:Kann ExecuteReader() zweimal verwendet werden?

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

Was für Probleme? Wie auch immer, versuchen Sie den Befehl auch zu entfernen. –

Antwort

2

vorgeschlagene Lösung: Versuchen Sie, einen using Block um Ihre DataReader setzen oder Dispose auf ihn nennen:

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

Vermutete Ursache des Problems: Die Verbindung DB-Objekt kann Führen Sie eine interne Buchführung durch, um die Datenleser im Auge zu behalten. Ich habe in einem ähnlichen Szenario herausgefunden, dass du nur eine DataReader gleichzeitig haben darfst. Also ich glaube, das Problem mit Ihrem Code ist, dass, während Sie Close die Reader, haben Sie nicht explizit Dispose d es, so dass das Verbindungsobjekt denkt, der erste Datenleser ist immer noch in Verwendung, wenn Sie die zweite ausführen.


Neben ... warum diesen Code nicht vereinfachen:

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

zu einer switch Aussage ?:

 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; 

(Das würde man ziemlich viel wiederholte Eingabe speichern .)

1

Nun, vorausgesetzt, dass Ihr Code richtig ist yo Sie sollten kein Problem damit haben, zwei Reader auszuführen, wie Sie es in Ihrem Code sehen. Vielleicht haben Sie Probleme, weil Sie keine Befehle oder etwas anderes haben. Ich empfehle einen Ansatz wie dieses (Beispiel mit Nordwind db gemacht):

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

Sie sollen Ihren Code sauber, wenn die Art von Spieler zu erkennen. Erstellen Sie eine Enumeration statt:

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

Und dann gehen Sie wie folgen der beim Lesen:

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

schlagen vor, eine player_type, player_class etc .. Tabelle vs eine enum –

Verwandte Themen