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

  1. #1
    Nouveau membre du Club
    Lire la clé primaire d'une valeur dans une table - TableAdapter
    Bonjour,

    Je ne maîtrise encore pas bien les Dataset, Tableadapter, Bindingsource etc.
    Je vais essayer de me faire comprendre.

    J'ai une première table dont un des champ (int) fournit à une seconde table (d'une seule colonne de 5 éléments) sa clé primaire.
    Je réussi à afficher dans mon formulaire les données qui résultent d'une requête appliquée sur la première table et j'obtiens les données de la seconde table qui est liée.

    Mais lorsque ensuite je veux enregistrer les modifications appliquées dans mon formulaire, j'ai besoin d'obtenir la clé primaire associée à la valeur liée à la seconde table, afin de l'écrire dans la première table.

    Je n'arrive pas à obtenir cet index. Il correspond à la clé primaire de la valeur présente dans ma seconde table.

    Je ne sais pas interroger la seconde table en passant comme argument ma valeur et obtenir sa clé primaire.

    Ma première Table se nomme "Items", la seconde "Gisement".

    J'utilise Tableadapter pour mes données.
    J'ai créé un tableAdapter associé à ma seconde table "Gisement" :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    SELECT RefGis FROM Gisement WHERE  (Gis = @GisString)

    Mais je ne sais pas comment m'en servir.

    J'ai essayé :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    int CleGis = this.gisementTableAdapter.FillByGisString(artcollectionDataSet.Gisement, ModifComboGis.Text.ToString());

    Mais cela me renvoie toujours la valeur "1".

    Merci

  2. #2
    Nouveau membre du Club
    Je précise un point.
    Il semble que lorsque j'utilise
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    int CleGis = this.gisementTableAdapter.FillByGisString(artcollectionDataSet.Gisement, ModifComboGis.Text.ToString());

    J'applique un filtre supplémentaire à celui qui m'a permis d'afficher les données dans mon formulaire.
    Mais je l'applique uniquement aux données de ma seconde table liée.
    Ce qui se passe c'est que je n'ai ensuite plus accès aux valeurs de la seconde table quand je parcours mes données via ma requête principale sur la première table.
    C'est comme si les tables n'étaient plus liées (enfin, c'est ainsi que je l'interprète).

    Ce que je voudrais c'est consulter les données de ma seconde table sans interférer avec le dataset généré par ma requête principale.
    J'espère que j'arrive à me faire comprendre.
    Merci

  3. #3
    Membre expert
    bonjour

    Tes 2 tables n’obéissent pas au schéma relationnel .
    La clé primaire de ta 2 ème table(table enfant) doit être indépendante => pour assurer l'unicité des enregistrements(rôle d'une clé primaire)

    Ta 2 ème table(table enfant) ne peut se référer aux enregistrements de ta
    1 ère table(table parente) que par une seconde clé dite "clé étrangère" ou "foreign key"(en fait un champ de même type et longueur que la clé primaire de la 1 ère table).

    Table Parente(1 ère Table)
    fld0 (clé primaire) *fld1 *fld2 *etc ...
    IdClient *nom *prénom *etc...

    Table Enfant(2 ème Table)
    fld0 (clé primaire) *fld1 *fld2 *etc ...*fld N(clé étrangère)
    IdCommande *montant *date *etc...*IdClient

    Ce schéma permet de faire la m.a.j des 2 tables en cascade (concepteur
    de tables et m.a.j en cascade) , d'afficher les 2 tables comme étant liées grâce à un DataSet et un "DataRelation" à explorer par tes soins.
    bon code.

  4. #4
    Nouveau membre du Club
    Bonjour,

    Merci pour ta réponse rapide.
    Mais j'ai du mal à la comprendre.
    C'est normal je crois, je patauge encore pas mal dans ces concepts.

    Je ne fais pas de tri à partir de la table enfant. Elle n'aura donc aucune influence sur les requêtes. Je m'en sers comme d'une liste de catégories.

    Voici en PJ une image du Dataset avec les relations.

    Je ne comprends pas comment (et par quel moyen ?) ajouter une clé étrangère pour ma table enfant me permettrait de faire ce que j'essaie de faire :
    Obtenir les valeurs de clé primaires de cette table en rapport avec chaque élément contenu dans cette table.
    Merci

  5. #5
    Membre expert
    bonjour
    Le method DataTable.Rows.Find() recherche un Row par sa CLE.
    La prop DataTable.Primary renvoie un tableau de DataColumn CLES .
    te seront utiles.
    Meme si ta clé primaire de la 2 eme table est définie en base de donnés,le code suivant censé retourner la colonne clé de ta table renverra null:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     private DataColumn GetPrimaryKeys(DataTable table)
            {
                // Create the array for the columns.
                DataColumn[] columns;
                columns = table.PrimaryKey;
     
                return columns[0];// 1ere colonne
            }


    Pour éviter cet inconvénient fâcheux ,il faut la définir par code explicitement juste après l'avoir ajouté au DataSet commun & "Fillé" par son DataAdapter .

    le code exemple qui suit illustre la méthode pour tes 2 tables
    Nota Bene : j'utilise SqlCommandBuilder pour simplifier les commandes Update,Delete et Insert.

    Il utilise 2 tables quelconques (pas de schéma relationnel).
    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
     
    using System.Data.SqlClient;
    namespace WinTablesOrphelines
    {
        public partial class Form2 : Form
        {
            private DataSet ds;
            private DataTable dtItems, dtGisements;
            private SqlDataAdapter daItems ,daGisements;
            private SqlCommandBuilder builderItems, builderGisements;
            private string strCon = string.Empty;
            private SqlConnection con = null;
            public Form2()
            {
                InitializeComponent();
            }
     
            private void Form2_Load(object sender, EventArgs e)
            {
                ds = new DataSet();
     
                strCon = GetConnectionString();
                con = new SqlConnection();
                con.ConnectionString = strCon;
                con.Open();
            }
     
            private void btnFillItemsbtnFillItems_Click(object sender, EventArgs e)
            {
                if (con == null) return;
                if (dtItems != null) ds.Tables.Remove(dtItems);
                dtItems=new DataTable("Items");
                ds.Tables.Add(dtItems);
                string strSelectItems = "SELECT * FROM Items ";
                daItems = new SqlDataAdapter(strSelectItems, con);
                builderItems = new SqlCommandBuilder();
                builderItems.DataAdapter = daItems;
                builderItems.GetUpdateCommand();
                builderItems.GetInsertCommand();
                builderItems.GetDeleteCommand();
     
                daItems.Fill(ds, dtItems.TableName);
                dgvItems.DataSource = dtItems;
            }
            private void btnFillGisements_Click(object sender, EventArgs e)
            {
                if (con == null) return;
                if (dtGisements != null) ds.Tables.Remove(dtGisements); 
                dtGisements = new DataTable("Gisements");
                ds.Tables.Add(dtGisements); 
     
                string strSelectGisements = "SELECT * FROM Gisements";
                daGisements = new SqlDataAdapter(strSelectGisements, con);
                builderGisements = new SqlCommandBuilder();
                builderGisements.DataAdapter = daGisements;
                builderGisements.GetUpdateCommand();
                builderGisements.GetInsertCommand();
                builderGisements.GetDeleteCommand();
     
                daGisements.Fill(ds, dtGisements .TableName);
                dgvGisements.DataSource = dtGisements ;
     
     
                // colonne KEY  specifié EXPLICITEMNT
                DataColumn[] keys = new DataColumn[1];
                DataColumn column;
     
     
                column = dtGisements.Columns[0];// C'EST ICI QUE CA SE PASSE
                keys[0] = column;
     
                dtGisements.PrimaryKey = keys;//ET ASSIGNATION 
     
            }
            private void btnSaveItems_Click(object sender, EventArgs e)
            {
                if (daItems != null)
                    daItems.Update(ds, dtItems.TableName);
     
            }
            static private string GetConnectionString()
            {
                return WinTablesOrphelines.Properties.Settings.Default.MaBdConnectionString;
            }
            private Random rnd = new Random();
            private void btnSaveGisements_Click(object sender, EventArgs e)
            {
                if (con == null) return;
                DataTable Items=ds.Tables["Items"];
                DataTable Gisements=ds.Tables["Gisements"];
     
                DataColumn col = GetPrimaryKeys(Gisements);
     
                foreach (DataRow item in Items.Rows)
                {
                    int numeroGis =(int) item["NumeroGis"];
                    DataRow gis = Gisements.Rows.Find(numeroGis);
                   if (gis ==null)  // SI CLE n'existe pas l'ajouter à Gisements
                   {  
                       DataRow dr =Gisements.NewRow();
                       dr[col.ColumnName]=numeroGis;
                       dr["Montant"] =rnd.Next(5000,6001);
                       dr["Anne"] =DateTime.Now.ToShortDateString(); 
     
                       Gisements.Rows.Add(dr);
     
                   }
                };
                if(daGisements !=null)
                    daGisements.Update(ds, dtGisements.TableName);
            }
     
            private DataColumn GetPrimaryKeys(DataTable table)
            {
                // Create the array for the columns.
                DataColumn[] columns;
                columns = table.PrimaryKey;
     
                return columns[0];// 1 ère colonne
            }
     
        }
    }

    bon code...

  6. #6
    Nouveau membre du Club
    Bonjour,

    J'ai testé votre solution.
    Elle ne correspond pas à ce que j'essaie de faire.
    Je ne cherche pas à ajouter une clé primaire dans ma table enfant si cette clé n'existe pas.

    Néanmoins, je suis parvenu à faire ce que je voulais en m'inspirant de la manière dont vous traitez les data.
    Je n'utilisais pas
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    using System.Data;

    J'étais donc, à mon avis, un peu trop loin de la structure des tables pour les interroger et m'en sortir.

    Voici le code que j'utilise :
    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
     
    private int Lire_Cle_Primaire_Table(string NomTable, string valeur)
            {
                DataTable TableTestee = artcollectionDataSet.Tables[NomTable];
     
                foreach (DataRow row in TableTestee.Rows)
                {
                    if (row[1].ToString() == valeur)
                    {
                        int numeroGis = (int)row[0];
                        Console.WriteLine(numeroGis.ToString());
                        return numeroGis;
                    }
                };
                return 0;
     
            }

    L'argument 'valeur' est le texte sélectionné dans un combobox par l'utilisateur.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
                int CleGis = Lire_Cle_Primaire_Table("Gisement", ModifComboGis.Text); // case = 0 >> Création de catégorie ?


    Un return à 0 signifiera que la valeur n'existe pas dans la table enfant. Je pourrai alors traiter, si nécessaire, son ajout (avec probablement votre code)

    CleGis me donne à présent bien la valeur int à mettre dans le champ Gisement de ma table parent pour prendre en compte la modification.

    Merci

  7. #7
    Nouveau membre du Club
    Suite à ce qui précède, lorsque j'applique Update à mon dataset, je perds la connexion à la base de données et les valeurs ne sont pas écrites dans la base.

    Est-ce que ce ne serait pas dû à l'utilisation de deux méthodes différentes d'accès aux données (c'est pourquoi je poste ce problème ici) ?

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
                try
                {
                    this.Validate();
                    this.itemsTableAdapter.UpdateTESTQuery(DimV, DimH, CleGis, CleCat, CleNat, CleRef);
                    MessageBox.Show("Update successful");
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show("Update failed", ex.ToString());
                }

    Aucun message d'erreur généré lors de l'exécution, le dataset est modifié mais aucun enregistrement dans la base !

    Est-ce que les méthodes Visual Studio (databinding etc) et System Data/System.Data.SqlClient d'accès aux données sont compatibles ?
    Merci