2016-08-23 1 views
0

Tout d'abord, désolé pour mon anglais :)C# Créer des boutons à partir de la base de données avec la ligne manquante

Je voudrais créer des boutons automatiquement à partir de la base de données. Dans la base de données, chaque bouton possède un identifiant et j'appelle cet identifiant.

Mon problème est simple, Si l'un des ID manque (comme 1,2,4,5), le programme s'arrête après la deuxième lecture. Voici le code:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Data.SqlClient; 

namespace e_res 
{ 
public partial class Layout : Form 
{ 
    public Layout() 
    { 
     InitializeComponent(); 
    } 

    private void Layout_Load(object sender, EventArgs e) 
    { 
     SQLFunctions Lgn = new SQLFunctions(); 
     Lgn.ConnectionToday(); 
     SqlCommand cmd = new SqlCommand(); 
     cmd.Connection = SQLFunctions.conn; 

     int NumOfButtons = 40; 
     int i = 1; 
     cmd.CommandText = "SELECT id FROM Buttons where id='" + i + "'"; 
     int _bId = Int32.Parse(cmd.ExecuteScalar().ToString()); 

     //   int counter = 0; 

     while (_bId <= NumOfButtons) 
     { 
      if (_bId != null) 
      { 
       Button btn = new Button(); 
       { 
        btn.Tag = _bId; 
        btn.Dock = DockStyle.Fill; 
        btn.Margin = new Padding(10, 10, 10, 10); 

        cmd.CommandText = "SELECT bName FROM Buttons where id='" + btn.Tag + "'"; 
        btn.Text = cmd.ExecuteScalar().ToString(); 
        string btn_name = cmd.ExecuteScalar().ToString(); 
        btn.Name = btn_name.ToString(); 

        /*     btn.Click += delegate 
             { 
              pass_txt.Clear(); 
              username_txt.Text = btn_name; 
              username_lbl.Text = btn_name; 
              username_lbl.Visible = true; 
              pass_txt.ReadOnly = false; 
             };*/ 

       } 
       cmd.CommandText = "SELECT col FROM Buttons where id='" + btn.Tag + "'"; 
       int btn_col = Int32.Parse(cmd.ExecuteScalar().ToString()); 
       //    MessageBox.Show(btn_col.ToString()); 
       cmd.CommandText = "SELECT row FROM Buttons where id='" + btn.Tag + "'"; 
       int btn_row = Int32.Parse(cmd.ExecuteScalar().ToString()); 
       //    MessageBox.Show(btn_row.ToString()); 
       tableLayoutPanel4.Controls.Add(btn, btn_col, btn_row); 
       _bId++; 
      } 
      else 
      { 
       _bId++; 
      } 
     } 
     SQLFunctions.conn.Close(); 

    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     NewButton nw = new NewButton(); 
     nw.Show(); 
    } 
} 




} 

Merci

+0

Tout d'abord, je vous suggère de réduire le nombre de requêtes, actuellement vous exécutez 3 par boucle. Je suggérerais 'select bname, col, row à partir des boutons où id <= NumOfButtons' en dehors de la boucle, puis accéder au jeu de résultats dans une boucle qui se termine quand il n'y a plus de lignes. Cela permettra également de résoudre votre problème actuel. –

+0

@AlexK. Merci, mais à première vue je ne peux pas imaginer comment tu le penses. Pouvez-vous donner un exemple? – Dris

Répondre

1

Voici certaines choses que vous avez vraiment besoin d'être regarder, je déduis de votre code encore votre nouveau à la programmation depuis réchaper de meilleurs bractices.

  1. int _bId = Int32.Parse(cmd.ExecuteScalar().ToString()); Ceci est dangereux
  2. Dans votre mise en page, vous avez une implémentation de la méthode entière, vous devez déplacer le code à sa propre méthode respectée et l'appeler de la mise en page.
  3. Pourquoi avez-vous besoin d'utiliser l'ID généré automatiquement par la base de données? vous pouvez générer automatiquement votre propre ID après avoir récupéré toutes les données d'une seule requête au lieu de 3 comme @Alex K. mentionné
  4. int NumOfButtons = 40; int i = 1; cmd.CommandText = "SELECT id FROM Boutons où id = '" + i + "'";

Vous ne savez pas combien de boutons que vous avez dans votre DB, vous ne pouvez pas coder en dur le numéro. à la place faire quelque chose comme ça "SELECT id, bName, col, ligne FROM Boutons;"

0
if (_bId != null) 
      { 
      // Here.. You need to check if _bId (For ex: 3) exists in database(by making a query), and then proceed with creating button which is rest of your code. 


      } 

Note: Vous n'avez pas besoin encore et encore interroger en boucle, vous pouvez récupérer toutes les données à la fois en utilisant ci-dessous.

SELECT bname, col, Ligne de boutons où id = ' "+ Bid +"'

Si cette requête retruns une ligne, // vous continuez avec le reste de votre code, créez bouton autre bId ++;

0

Utilisez ExecuteReader() avec une requête qui sélectionne tous les boutons. Je suppose que MS Sql Sever soutien TOP()

cmd.CommandText = "SELECT TOP(" + NumOfButtons + ") id, bname,col,row FROM Buttons ORDER BY id"; 
    SqlDataReader reader = cmd.ExecuteReader(); 
    while (reader.Read()) 
    { 
     // process the button 
    } 
0

Si nous sauter la partie « votre approche est pas vraiment efficace », mais juste essayer de faire ce code de travail, alors vous devriez modifier pour ressembler à ceci:

SQLFunctions Lgn = new SQLFunctions(); 
Lgn.ConnectionToday(); 
SqlCommand cmd = new SqlCommand(); 
cmd.Connection = SQLFunctions.conn; 

int NumOfButtons = 40; 
int i = 1; 

//   int counter = 0; 

while (i <= NumOfButtons) 
{ 
    cmd.CommandText = "SELECT id FROM Buttons where id='" + i + "'"; 

    int _bId = Int32.Parse(cmd.ExecuteScalar().ToString()); 

    Button btn = new Button(); 
    { 
     btn.Tag = _bId; 
     btn.Dock = DockStyle.Fill; 
     btn.Margin = new Padding(10, 10, 10, 10); 

     cmd.CommandText = "SELECT bName FROM Buttons where id='" + btn.Tag + "'"; 
     btn.Text = cmd.ExecuteScalar().ToString(); 
     string btn_name = cmd.ExecuteScalar().ToString(); 
     btn.Name = btn_name.ToString(); 

     /*     btn.Click += delegate 
     { 
     pass_txt.Clear(); 
     username_txt.Text = btn_name; 
     username_lbl.Text = btn_name; 
     username_lbl.Visible = true; 
     pass_txt.ReadOnly = false; 
     };*/ 

    } 
    cmd.CommandText = "SELECT col FROM Buttons where id='" + btn.Tag + "'"; 
    int btn_col = Int32.Parse(cmd.ExecuteScalar().ToString()); 
    //    MessageBox.Show(btn_col.ToString()); 
    cmd.CommandText = "SELECT row FROM Buttons where id='" + btn.Tag + "'"; 
    int btn_row = Int32.Parse(cmd.ExecuteScalar().ToString()); 
    //    MessageBox.Show(btn_row.ToString()); 
    tableLayoutPanel4.Controls.Add(btn, btn_col, btn_row); 

    i++; 

} 
SQLFunctions.conn.Close(); 

Mais si nous parlons de code que je voudrais vraiment utiliser pour résoudre votre cas, je changerais colonne de type int Id et 1 simple, commande SQL a pris la première NumOfButtons de la table commandée par Id.Voici simple requête SQL qui travaillerait:

SELECT id, col, row ORDER BY id FETCH NEXT (@NumOfButtons) ROWS ONLY

Et j'utiliser cette structure pour l'exécuter:

using (var reader = cmd.ExecuteReader($"SELECT id, col, row ORDER BY id FETCH NEXT ({NumOfButtons}) ROWS ONLY")) 
{ 
    while (reader.Read()) 
    { 
     var id = reader.GetInt32(0); 
     var col = reader.GetString(1); 
     var row = reader.GetString(2); 

     // ToDo: Your stuff here 
    } 
} 
0

Savez-vous ce que la séquence sera-à-dire est contiguë à- dire qu'il va commencer à un certain nombre et devrait augmenter de 1 à chaque fois? Si tel est le cas, je peux vous donner un peu de pseudo code qui devrait résoudre votre problème. Je n'ai pas de studio visuel à portée de main pour vérifier tout le code. Puis, écrivez une instruction linq qui trouve l'ID le plus bas dans la séquence. Ensuite, écrivez une instruction linq qui trouve l'ID le plus élevé dans la séquence.

Ensuite, utilisez un

int last = lowest; 
for (int i = lowest; i <= highest; i++) 
{ 
int curr = (from int btn in collection/datatable where btn.ID == i select btn.ID).first; 

if (curr == (last + 1)) 
{ 
curr = i; 
} 
else 
{ 
++last 
curr = last; 
} 

    //make the button based on curr or not as needed 

++last; 
} 
}