0
votes

Comment supprimer des enregistrements spécifiques d'une table dans Visual Studio?

J'ai écrit et réécrit le code plusieurs fois maintenant pour supprimer les enregistrements en entrant le «nom» dans une zone de texte et en cliquant sur un bouton qui supprimera la ligne relative au nom entré. Cependant, lorsque j'exécute le programme et clique sur le bouton, la boîte de message apparaît indiquant que les enregistrements particuliers ont été supprimés, mais lorsque la table est affichée dans la vue de la grille de données, les enregistrements sont toujours présents (ils n'ont pas été supprimé du tableau) Veuillez vérifier mon codage et me dire ce qui ne va pas et comment le résoudre? merci :) Aussi je dois dire que je n'ai appris que des trucs basiques en programmation C # .. Voici mon codage:

private void btnremove_Click(object sender, EventArgs e)
{
    con.Open();
    DialogResult ans = MessageBox.Show("Are you sure you want to remove the selected records?", 
        "Confirmation For Membership Cancellation", MessageBoxButtons.YesNo, 
        MessageBoxIcon.Question);
    if (ans==DialogResult.Yes)
    {
        string sqldelete = "DELETE FROM membersdetails WHERE Name='" + txtname.Text + "'";
        string deletesql = "DELETE FROM currentstatus WHERE Name_='" + txtname.Text + "'";
        com = new SqlCommand(sqldelete,con);
        com = new SqlCommand(deletesql, con);
        SqlDataAdapter sqldataadapter = new SqlDataAdapter(com);
        com.ExecuteNonQuery();
        MessageBox.Show("Records have been removed- Membership has been  cancelled", 
           "Membership Cancellation", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    con.Close();
    com.Dispose();
}


1 commentaires

Le DGV n'est pas automatiquement repeint lorsque les données sont mises à jour. Vous devez à nouveau interroger la base de données ou la supprimer du DataSet.


3 Réponses :


0
votes

Il y a quelques problèmes avec votre code, dans son état actuel:

  1. Le bloc ci-dessous, vous écrasez une partie de votre mécanisme de suppression:

        com = new SqlCommand(sqldelete,con);
        com = new SqlCommand(deletesql, con);
        SqlDataAdapter sqldataadapter = new SqlDataAdapter(com);
        com.ExecuteNonQuery();
    

    Vous devriez être en mesure de fusionner les variables de chaîne sqldelete et deletesql une deletesql commande, qui peut ensuite être transmise au moteur de base de données.

  2. Du point de vue du codage, les classes doivent respecter le principe de responsabilité unique, c'est-à-dire que les classes se soucient de ne faire qu'une seule chose. Dans votre code actuel, l'interface utilisateur doit examiner la mise à jour de l'interface utilisateur et la mise à jour de la base de données. Pour résoudre ce problème, nous créons généralement des référentiels dont la tâche est de boucler les opérations de la base de données. Cela vous permet également de tester des couches individuelles de votre application et vous donne également plus de flexibilité si vous décidez d'apporter des modifications.

  3. En l'état, votre code est ouvert aux attaques par injection SQL, pensez à utiliser des instructions préparées pour résoudre ce problème.

  4. À part cela, je ne vois rien de fondamentalement incorrect avec votre code de suppression. Cependant, il se peut que votre grille ne soit pas actualisée (pendant que vous pensez que c'est le cas). Le moyen le plus rapide et le meilleur pour vérifier cela consiste à utiliser quelque chose comme SQL Management Studio (ou Azure Data) pour vous connecter à votre base de données et interroger directement la table.


0 commentaires

0
votes

Le ExecuteNonQuery() doit être exécuté après et avant de la dernière nouvelle instance:

    com = new SqlCommand(sqldelete,con);
    com.ExecuteNonQuery();
    com = new SqlCommand(deletesql, con);
    com.ExecuteNonQuery();
    
    // Then, you can show the table
    string sqlSelect = "SELECT * FROM yourtable WHERE bla bla...";
    SqlDataAdapter sqldataadapter = new SqlDataAdapter(sqlSelect, con);
    DataTable tbl = new DataTable();
    sqldataadapter.Fill(tbl);
    yourDataGridView.DataSource = tbl;

Essayez ceci, j'espère que cela pourrait vous aider.


0 commentaires

0
votes

Voici un exemple qui peut nécessiter des modifications pour s'adapter à votre code. L'idée est de configurer une source de données DataGridView avec un BindingSource qui a requis des colonnes d'une table pour les détails des membres. Les opérations de données sont dans une classe pour séparer les opérations frontales des opérations de données. Notez qu'il n'y a pas besoin d'un SqlDataAdapter qui est excessif.

Pour l'opération de suppression, il est préférable d'utiliser une clé primaire car elle est constante alors qu'un nom peut changer à un moment donné.

La classe suivante est une maquette pour les opérations de lecture et de suppression, assurez-vous de bien comprendre que ce n'est pas une solution de copier-coller, prenez donc le temps de lire le code avant de l'essayer.

Classe de données

using System;
using System.Windows.Forms;

namespace YourNamespace
{
    public partial class Form1 : Form
    {
        private readonly BindingSource _membersBindingSource = new BindingSource();
        public Form1()
        {
            InitializeComponent();
            Shown += Form1_Shown;
        }
        /// <summary>
        /// Setup columns in the IDE for MembersDataGridView that
        /// exclude the primary key
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Shown(object sender, EventArgs e)
        {
            MembersDataGridView.AutoGenerateColumns = false;
            _membersBindingSource.DataSource = MembershipOperations.GetMemberDetails();
            MembersDataGridView.DataSource = _membersBindingSource;
        }

        private void RemoveMemberButton_Click(object sender, EventArgs e)
        {
            if (_membersBindingSource.Current == null) return;

            var member = (MemberDetails)_membersBindingSource.Current;

            if (!Dialogs.Question($"Remove {member}")) return;

            if (!MembershipOperations.RemoveSingleOrder(member.Id))
            {
                MessageBox.Show($"Failed to remove {member}");
            }
        }
    }
}

La méthode d'aide pour poser une question avec le bouton par défaut est Non, pas Oui.

en utilisant System.Windows.Forms;

namespace YourNamespace
{
    public static class Dialogs
    {
        public static bool Question(string text)
        {
            return (MessageBox.Show(
                text,
                Application.ProductName,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button2) == DialogResult.Yes);
        }
    }
}

Code de formulaire

using System.Collections.Generic;
using System.Data.SqlClient;

namespace YourNamespace
{
    public class MembershipOperations
    {
        /// <summary>
        /// Connection string to your database
        /// - change TODO to your environment
        /// - Integrated Security (check this too)
        /// </summary>
        private static readonly string _connectionString =
            "Data Source=****TODO****;" +
            "Initial Catalog=****TODO****;" +
            "Integrated Security=True";

        /// <summary>
        /// Delete a single member by primary key
        /// Recommend adding a try-catch to the open and ExecuteNonQuery lines
        /// </summary>
        /// <param name="memberIdentifier">Member primary key</param>
        /// <returns>
        /// Success of the operation
        /// </returns>
        public static bool RemoveSingleOrder(int memberIdentifier)
        {
            bool success = false;

            string deleteStatement = "DELETE FROM membersdetails  WHERE id = @id";

            using (var cn = new SqlConnection { ConnectionString = _connectionString })
            {
                using (var cmd = new SqlCommand { Connection = cn, CommandText = deleteStatement })
                {

                    cmd.Parameters.AddWithValue("id", memberIdentifier);
                    cn.Open();
                    success = cmd.ExecuteNonQuery() == 1;
                }
            }

            return success;

        }
        /// <summary>
        /// Provides a list which in the frontend a user can select
        /// a member such as a ComboBox or ListBox etc.
        ///
        /// When they select a user you have code to cast the selected item
        /// to a MemberDetails instance and pass the primary key to the RemoveSingleOrder
        /// method.
        ///
        /// Note in the frontend if there are many members consider providing a incremental
        /// search feature to the frontend control displaying member details.
        /// </summary>
        /// <returns></returns>
        public static List<MemberDetails> GetMemberDetails()
        {
            var memberDetails = new List<MemberDetails>();

            /*
             * - Create a connection and command object with
             *   SELECT column names including 'id' primary key
             *
             * - Use a DataReader to loop through records into
             *   memberDetails variable
             */

            return memberDetails;
        }
    }
    /// <summary>
    /// Place in a class file named  MemberDetails.cs
    /// </summary>
    public class MemberDetails
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        // more properties

        /// <summary>
        /// Optional, can assist with debugging and/or
        /// for display purposes
        /// </summary>
        /// <returns></returns>
        public override string ToString() => $"{FirstName} {LastName}";

    }
}


0 commentaires