IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Dataadapter.update ne fonctionne pas pour les suppressions


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre extrêmement actif Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    2 039
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 2 039
    Par défaut Dataadapter.update ne fonctionne pas pour les suppressions
    Bonjour

    Je débute avec ADO.net avec une base SQLite qui me sert à charger une DataTable "TableServeurs" que je met comme DataSource d'un DataGridView

    Au chargement tout se passe bien

    Ensuite j'ai un bouton pour ajouter une ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                DataRow dr = Store.SingletonInstance.TableServeurs.NewRow();
                dr["Description"] = textBoxRef.Text ;
                dr["HostName"] = textBoxHostName.Text ;
     
                Store.SingletonInstance.AddServeur(dr);
    Dans la classe Store (un singleton) j'ai
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public void AddServeur(DataRow item)
            {
                if (TableServeurs != null)
                {
                    TableServeurs.Rows.Add(item);
                    SaveDataTable(TableServeurs);
                }
            }
    avec le SaDataTable ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public void SaveDataTable(DataTable DT)
            {
                try
                {
                    con.Open();
                    cmd = con.CreateCommand();
                    cmd.CommandText = string.Format("SELECT * FROM {0}", DT.TableName);
                    adapter = new SQLiteDataAdapter(cmd);
                    SQLiteCommandBuilder builder = new SQLiteCommandBuilder(adapter);
                    adapter.Update(DT);
                    con.Close();
                }
                catch (Exception Ex)
                {
                    MessageBox.Show(Ex.ToString(), "Erreur !", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                }
            }
    Ca fonctionne parfaitement. idem pour une modification d'une ligne, c'est mis à jour et la base de donnée est bien modifiée avec les changements.

    PROBLEME :
    pour supprimer une ligne je fais ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Store.SingletonInstance.RemoveServeur(((DataRowView)dataGridView1.SelectedRows[0].DataBoundItem).Row);
    Dans Store.cs il y a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public void RemoveServeur(DataRow item)
            {
                        TableServeurs.Rows.Remove(item);
                        SaveDataTable(TableServeurs); //fonctionne pour les ajout et les modifications, pas pour l'effacement d'une ligne.
                    }
    la ligne est bien supprimée du Datatable mais ne l'est pas dans la base de donnée, pourquoi ???

    Merci par avance pour vos explications

  2. #2
    Membre extrêmement actif Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    2 039
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 2 039
    Par défaut
    Le adapter.update fait son boulot quand je supprime la ligne dans le datagridview plutôt que dans la datatable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (dataGridView1.SelectedRows.Count > 0)
                    {
                        dataGridView1.Rows.RemoveAt(dataGridView1.SelectedRows[0].Index);
                        Store.SingletonInstance.SaveDataTable(Store.SingletonInstance.TableServeurs);
                    }
    Dans la chaine Bdd -> dataTable -> datagridView
    >si j'efface la ligne dans le DataTable le adapter.update ne fonctionne pas
    > si j'efface la ligne dans le datagridview le adapter.update fonctionne pourtant la DataTable étant datasource du datagridview une modif sur la datatable ou sur le datagridview c'est pareil (d'apparence)

    Pourtant j'aimerais bien passer par le datatable afin de pouvoir séparer l'IHM du traitement des datas ; une idée avec ce nouvel élément ?

    Merci

  3. #3
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 001
    Par défaut
    As-tu regardé les logs SQL générés ?

    Je ne connais pas SQLite alors je ne sais pas quelles informations remontent où non.
    Mais si tu as peut-être une contrainte d'intégrité fonctionnelle (ou contrainte d'intégrité référentielle, ça dépend des gens) qui t'empêche de supprimer cet enregistrement ?
    Ou un trigger ?

  4. #4
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    re

    la ligne est bien supprimée du Datatable mais ne l'est pas dans la base de donnée, pourquoi ???
    Point important :il y a une distinction est à faire ,lors d'utilisation de "subtil" DataAdapter

    1/ Lignes marquées "Deleted" dans DataTable Aka Canditates à la Suppression par le DataAdapter
    et "Deleter" par DataRow.Remove() c.à.d un method du DataRow
    2/ Lignes supprimées réellement dans DataTable Aka par DataTable.Remove(ItemDataRow) ou DataTable.RemoveAt(index)

    Le DataAdapter ne supprime que les lignes du 1e cas
    Le DataAdapter ne peut supprimées les lignes du 2 cas ,puisque introuvables dans la DataTable ...
    Car il doit fournir les references des lignes à supprimer au driver OledDB ou SQLDB de la bd....!!!
    Par suite dans le 2e cas,ton cas justement ,il faut eviter de supprimer dans le DGV car il est repercute sur le DataTable comme DataTable.Remove() ou DataTable.RemoveAt()

    D'où l'echec de la commande Adapter.Update ....

    code behind.cs revu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    DataRow dr = ((DataRowView)dataGridView1.SelectedRows[0].DataBoundItem).Row;
               dr.Delete();
     
    public void RemoveServeur(DataRow item)
            {
                        //TableServeurs.Rows.Remove(item)   A VIRER  ;
                        SaveDataTable(TableServeurs); //fonctionne pour les ajout et les modifications, pas pour l'effacement d'une ligne.
                }
    bon code ...

  5. #5
    Membre extrêmement actif Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    2 039
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 2 039
    Par défaut
    Là je dois avouer que je ne sais plus ou j'en étais de mes galères...

    J'arrive depuis quelques jours à effacer les lignes en faisant ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     private void EffacerLigne()
    {
     if (dataGridView1.SelectedRows.Count > 0)
    {
       dataGridView1.Rows.RemoveAt(dataGridView1.SelectedRows[0].Index);
       Store.SingletonInstance.SaveDataTable(Store.SingletonInstance.TableServeurs);
    }
    }
    fonction que j'appelle dans la Form sur keydown ou button.click

    et dans la classe Store (singleton) j'ai la fonction d'enregistrement de la DataTable en base de donnée avec rechargement de la Datatable dans la foulée pour récupérer l'identifiant de ligne que SQlite a mis.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    /// <summary>
            /// Sauvegarde le DataTable en Base de donnée et le recharge à partir de la base de données (pour récupérer les numéro ID automatiques)
            /// </summary>
            /// /// <param name="DT">Datatable à enregistrer en base de donnée</param>
            public void SaveDataTable(DataTable DT)
            {
                try
                {
                    con.Open();
                    cmd = con.CreateCommand();
                    cmd.CommandText = string.Format("SELECT * FROM {0}", DT.TableName);
                    adapter = new SQLiteDataAdapter(cmd);
                    SQLiteCommandBuilder builder = new SQLiteCommandBuilder(adapter);
                    adapter.Update(DT);
                    DT.Clear();
                    adapter.Fill(DT); // rechargement du datatable
                    con.Close();
                }
                catch (Exception Ex)
                {
                    MessageBox.Show(Ex.ToString(), "Erreur !", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                }
            }
    Je suis donc dans le cas 1) et donc ça fonctionne si je comprends bien le dernier post
    C'est bon comme manière de faire ?

    Merci

  6. #6
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    Rebonjour
    Tu peux faire une "Deletion" sur le DataRowView au lieu d'acceder au DataRow( dr.Delete() ) comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
     ((DataRowView)dataGridView1.SelectedRows[0].DataBoundItem).Delete();

    Pour plus de clarté ,je poste le code complet suivant du class StoreTable revu en fonction de l'utilisation
    1/ d'un DataTable
    2/ d'un DataAdapter
    3/de son Acolyte CommandBuilder qui fournit son updating logic

    4/du Databing revu dans les 3 Forms chacun dédiés chacun :
    - MainFormAdd =>Ajout
    - FormUpdate =>Maj
    - FormDelete => Deletion
    Le Databing illustre le role du mystérieux DataView agissant en coulissant à notre insu....
    Le DataView dispose de nbreuses fonctionnalités: FindRow ,FindRows,Sort,RowFilter
    DataView doit etre trie sur un 1 champ CLE ou 2 champs CLE de recherche(Sort)....
    DataView
    L'architecture est extrement simple :
    code behind .cs du class StoreDtaTable:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
     
    //simplistic class StoreDataTable
        public class StoreDataTable
        {
     
            private string connectionString ="Provider=Microsoft.ACE.OLEDB.12.0;" +
                "Data Source=C:/Users/OUNIS/Desktop/"+
                "Projects/WinAppComponent/BDProduitsBis.mdb;";
            private OleDbDataAdapter da = null;
     
     
            public string  Message { get; set; }
            public DataTable Produits { get; set; }
     
            public StoreDataTable()
            {
                Message = "message";
                Produits = GetProduitTable();
            }
     
     
            private DataTable GetProduitTable()
            {
                DataTable dt = null;
                string selectSQL = "SELECT * FROM Produit;";
     
                // Ce Ctor utilise connection optimise interne du Adapter  
                // le DataAdapter l'ouvre et la referme à chaque appel 
                // à son method DataAdapter.Update()
                da = new OleDbDataAdapter(selectSQL, connectionString);
     
     
     
                // Son Acolyte  CommandBuilder fournit son  updating logic.
                OleDbCommandBuilder cb = new OleDbCommandBuilder(da);
                Console.WriteLine(cb.GetInsertCommand().CommandText );
                Console.WriteLine(cb.GetUpdateCommand().CommandText);
     
                //Handle the RowUpdating event to batch the update.
                da.RowUpdating += new OleDbRowUpdatingEventHandler(da_RowUpdating);
                da.RowUpdated += new OleDbRowUpdatedEventHandler(da_RowUpdated);
     
                // Datatable
                dt = new DataTable("TableProduit");
                da.TableMappings.Add("TableProduit", "Produit");
     
                // Fill  schema  
     
                da.FillSchema(dt, SchemaType.Source);
     
                // Fill datatable
                da.Fill(dt);
     
                return dt ;
            }
     
     
     
           private  void da_RowUpdating(object sender, OleDbRowUpdatingEventArgs e)
            {
                Message = "DataAdapter.RowUpdating:" + Environment.NewLine + e.Command.CommandText;
            }
           private void da_RowUpdated(object sender, OleDbRowUpdatedEventArgs e)
            {
                Message = Environment.NewLine + "DataAdapter.RowUpdated: RecordsAffected = " + e.RecordsAffected;
            }
           // Et son SIMPLISTIC method Update
            public void Update()
            {
     
                try
                {
     
                    this.da.Update(Produits);
     
                }
                catch (DBConcurrencyException ex)
                {
                    string customErrorMessage ;
                    customErrorMessage = "Concurrency violation" + Environment.NewLine;
                    customErrorMessage += (string)ex.Row[0];
                    MessageBox.Show(customErrorMessage);
     
                    throw;
                }
            }
     
     
        }
    code behind .cs du class Program ou ton Singleton:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
     
     static class Program
        {
            private static StoreDataTable _storeDB = new StoreDataTable();
            public static StoreDataTable StoreDB
            {
                get { return _storeDB; }
            }
            /// <summary>
            /// Point d'entrée principal de l'application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new MainFormAdd());
            }
        }

    code behind .cs des 3 Forms utilisateurs;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
     
    // Form MAIN
        public partial class MainFormAdd : Form
        {
            private List<Form> ownedForms = new List<Form>();
            public MainFormAdd()
            {
                InitializeComponent();
                ownedForms.Add(new FormUpdate());
                ownedForms.Add(new FormDelete());
                foreach (var item in ownedForms)
                {
                    this.AddOwnedForm(item);
                }
            }
     
            private void btnLoadProduits_Click(object sender, EventArgs e)
            {
                BindRefresh();
            }
            //TOUT BINDING EST FAIT REELLEMENT PAR L'API SUR LA COUCHE DATAVIEW "INTERPOSÉE" EN INTERNE SUR TOUTE SOURCE DE BINDING ICI LA DATATABLE PRODUITS  
            //ICI JE L'EXPLICITE !!!
            private void BindRefresh()
            {
                // Configation de la maudite DataView
                //si on met false le DGV  deviendra un socle en pierre !!!
     
                Program.StoreDB.Produits.DefaultView.AllowNew = true;//ajout dans dgv autorisee
                Program.StoreDB.Produits.DefaultView.AllowDelete = true;//"Delete" dans dgv autorisee non suppressionou remove (voir FormDelete et btnDelete) 
                Program.StoreDB.Produits.DefaultView.AllowEdit = true; //edition dans dgv autorisee
     
     
                this.dataGridView1.DataSource = Program.StoreDB.Produits.DefaultView;
                this.dataGridView1.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
            }
     
            private void btnShowFormUpdate_Click_1(object sender, EventArgs e)
            {
                ownedForms[0].Show();
     
            }
     
            private void btnShowFormDelete_Click(object sender, EventArgs e)
            {
                ownedForms[1].Show();
            }
            private void btnAddProduit_Click(object sender, EventArgs e)
            {
                lblMessage.Text = "";
                DataRow dr = Program.StoreDB.Produits.NewRow();
     
                //NOTA BENE :dr["ID"]  un champ cle  autoincremente en base n'est pas specifie
     
                dr["Description"] = "newDesc";
                dr["HostName"] = "new item";
                dr["PortFTP"] = "1500";
                Program.StoreDB.Produits.Rows.Add(dr);
     
                Program.StoreDB.Update();
                lblMessage.Text = Program.StoreDB.Message;
                BindRefresh();
            }
     
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                foreach (var item in ownedForms)
                {
                    this.RemoveOwnedForm(item);
                }
            }
     
     
        }
     
    //
     
    public partial class FormUpdate : Form
        {
            //FORM OWNED 1
            public FormUpdate()
            {
                InitializeComponent();
     
            }
            private void FormUpdate_Load(object sender, EventArgs e)
            {
                BindRefresh();
     
            }
            private void BindRefresh()
            {
     
                this.dataGridView1.DataSource = Program.StoreDB.Produits.DefaultView;
                this.dataGridView1.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
            }
     
            private void btnUpdate_Click(object sender, EventArgs e)
            {
                if (dataGridView1.SelectedRows.Count > 0)
                {
                    DataRow dr = ((DataRowView)dataGridView1.SelectedRows[0].DataBoundItem).Row;
                    Program.StoreDB.Update();
                    lblMessage.Text = Program.StoreDB.Message;
     
                    BindRefresh();
                }
            }
     
            private void btnHide_Click(object sender, EventArgs e)
            {
                this.Hide();
     
            }
     
            private void FormUpdate_FormClosing(object sender, FormClosingEventArgs e)
            {
                e.Cancel = true;
            }
        }
     
     
    //
     public partial class FormDelete : Form
        {
            public FormDelete()
            {
                InitializeComponent();
     
     
            }
     
     
            private void FormDelete_Load(object sender, EventArgs e)
            {
                BindRefresh();
     
            }
            private void BindRefresh()
            {
     
                this.dataGridView1.DataSource = Program.StoreDB.Produits.DefaultView;
                this.dataGridView1.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
            }
     
     
     
            private void btnDelete_Click(object sender, EventArgs e)
            {
                if (dataGridView1.SelectedRows.Count > 0)
                {
                    // un Row.Delete suffit !!! 
                    DataRow dr = ((DataRowView)dataGridView1.SelectedRows[0].DataBoundItem).Row;
                    dr.Delete();
     
                    Program.StoreDB.Update();
                    lblMessage.Text = Program.StoreDB.Message;
     
                    BindRefresh();
                }
     
            }
            private void btnHide_Click(object sender, EventArgs e)
            {
                this.Hide();
            }
            private void Form3_FormClosing(object sender, FormClosingEventArgs e)
            {
                e.Cancel = true;
            }
     
        }
    Bon code ............

Discussions similaires

  1. SaveChanges ne fonctionnant pas pour les mises en formes de cellules
    Par hichemnho dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 10/05/2014, 17h53
  2. Code ne fonctionne pas pour les sous dossiers
    Par archi57 dans le forum VBScript
    Réponses: 10
    Dernier message: 18/02/2012, 15h24
  3. [XL-2010] Boucle For qui ne fonctionne pas pour toutes les valeurs
    Par pleskyd dans le forum Macros et VBA Excel
    Réponses: 15
    Dernier message: 13/02/2012, 15h16
  4. Réponses: 3
    Dernier message: 03/01/2010, 20h53
  5. Réponses: 3
    Dernier message: 11/03/2008, 19h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo