none
Le dernier record de mon DataGridView n'est pas correctement updater dans ma database RRS feed

  • Question

  • Bonjour,

    J'ai besoin d'un coup de main sur un problème d'Update...  Pour être le plus claire possible, je vous expose le contexte et ce que j'ai compris de mon instigation:

    Tout d'abord le contexte:
    Un Winfo
    rm composé d'un ListBox (_lbKatas) et d'un DataGridView (_dvTechnics) expose les données sous forme d'un Master/Details: Dans le ListBox se trouve des records dont le détail est rendu dans le DataGridview.

    J'ai créé un DataSet typé 
    (_katasDataSet) avec 2 tables liées par une relation (parent/child)... La table parent s'appele "Katas" et la table child est "Technics".

    Le ListBox est lié à la table Katas, le DataGridView est lié à la tables Technics...

    J'ai défini la règle CASCADE sur l'UPDATE et le DELETE de mon dataset typé.

    Lorsqu'on consulte ou qu'on supprime des données tout est OK (en cas de suppression la DB est bien mis à jour)

    Le problème se produit lorsque l'on ajoute des données:

    1) l'utilisateur créer un nouveau récord dans le ListBox.
    private void btnNewKata_Click(object sender, EventArgs e)
    {
    string kataName = InputBox.Show("Please insert the name of the new Kata to create", "Create new Kata");
    if (kataName == "") return;
    KatasDataSet.KatasRow row = _katasDataSet.Katas.NewKatasRow();

    row.Name = kataName;
               _katasDataSet.Katas.Rows.Add(row);
               _lbKatas.SelectedIndex = _lbKatas.Items.Count - 1;
    }

    2) L'utilisateur ajoute un nouveau record pour le datagridview

    private void _btnNewTechnic_Click(object sender, EventArgs e)
    {
           //Retrieve the corresponding CurrencyManager and position the current record to the last row
          CurrencyManager cm = _dvTechnics.BindingContext[_dvTechnics.DataSource, _dvTechnics.DataMember] as CurrencyManager;
          if (cm == null) return;

         KatasDataSet.TechnicsRow newRow = _katasDataSet.Technics.NewTechnicsRow();
         newRow.KataId = (int)_lbKatas.SelectedValue;
          _katasDataSet.Technics.AddTechnicsRow(newRow);
         cm.Position = _katasDataSet.Technics.Rows.Count - 1;
         newRow.Position = cm.Position + 1;
    }

    3) L'utilisateur clique sur le bouton 'Save' de son application:
    private void saveToolStripMenuItem_Click(object sender, EventArgs e)
    {
            ForceEndEdit();
            if (IsDataDirty) SaveChanges();
    }

    private void ForceEndEdit()
    {
    _lbKatas.BindingContext[_lbKatas.DataSource].EndCurrentEdit();
    _dvTechnics.BindingContext[_dvTechnics.DataSource, _dvTechnics.DataMember].EndCurrentEdit();
    }

    La procédure SaveChanges() utilise un composant qui parcourt le dataset et fait les Update() sur les tables dans l'ordre adéquat pour respecter les contraintes de clés.

    Voici les résultats de mon investigation:

    Au moment du Update() pour la table Technics... Toutes les commandes Insert fonctionnent sauf pour le dernier record insérer dans le DataGridView... Il y a un probleme de foreign key sur le dernier record introduit par l'utilisateur dans le DataGridView... Pour tout les autres, le foreign key passé en parametre à la commande insert correspond bien à la clé identifier le record de la table Katas.

    Plus étrange encore... Dans la gestion d'évenement OnRowUpdated du DataAdapter de la table Technics, j'ai comparé la valeur de foreign key en fonction des DataRowVersions: row[2,DataRowVersion.Current] = row[2,DataRowVersion.Proposed] = le bon id...

    Mais la requête INSERT envoyé au server SQL donnne un mauvais foreing key !!!!!

    Du coup j'ai l'erreur:
    "The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Technics_Katas". The conflict occurred in database "KataContestDB", table "dbo.Katas", column 'Id'.
    The statement has been terminated."

    Mon intuissons me dit qu'il y a un problème de Focus ou de Validate() a faire sur le DataGridView... J'ai essayer plein de truc mais sans succès... (forcer la perte du focus, invoqués Validate sur tout les control de mon winforms... Rien n'y fait)

    Vous avez une idée de votre côté ?

    jeudi 20 novembre 2008 16:44

Toutes les réponses

  • Bonjour,

     

    Est-il possible que vous puissiez m'envoyer une de votre projet (ou un autre projet) qui reproduirait le problème sur l'adresse : gilles.tourreau@pos.fr ?

     

    Cordialement

     

    dimanche 23 novembre 2008 21:34
    Modérateur
  • je propose encore mieux...

    Le code source est libre d'accès sur Google Code: http://code.google.com/p/judo-kata-tournament-db/source/checkout

    Il suffit d'utiliser un client SVN pour récupérer toute la solution.

    Pour reproduire le problème il vaut faudra suivre les étapes suivantes:
    1. Installer la base de données "KataContestDatabase.mdf" situé dans le sous répertoire DataBase (Il s'agit d'une DB SQL server 2005
    2. Lancer l'application en mode Debug depuis Visual Studio...
    3. Dans la fenêtre de l'application: cliquer sur le Menu Edit > Katas
    4. Dans la fenêtre "Edit Katas" Ajouter créer un nouveau kata en cliquant sur le bouton "+New" ... Important N'appuyer pas encore sur le bouton "Save"
    5. Dans le panel "Technics" appuyer sur le bouton "+New" pour y ajouter une nouvelle technique... Introduisez ensuite un nom dans le champ "Technic's Name"
    6. Recommencez l'opération précédente (étape 5) autant de fois que vous le voulez....
    7. Appuyer sur le bouton "Save" de la fenêtre "Edit Katas"
    Au moment de la sauvegarde, le dernier récord que vous avez introduit remontra le problème que j'ai mentionné...

    Pour intercepter les commandes SQL lancées par l'application à SQL Server 2005, j'ai utilisé SQL Profiler
    La commande qui pause problème est la requête INSERT correspondant au dernier record ajouté dans le panel "Technics"

    J'espère avoir été assez claire.

    Merci pour votre aide

    lundi 24 novembre 2008 10:26