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

Entity Framework Discussion :

Update sur une table Many-to-Many


Sujet :

Entity Framework

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé

    Inscrit en
    Février 2007
    Messages
    253
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Février 2007
    Messages : 253
    Par défaut Update sur une table Many-to-Many
    Bonjour à tous.

    Ça fait au moins 8 heures que je cherche comment mettre à jour une relation many to many.

    J'ai un utilisateur qui contient une liste de profiles

    Table des profiles :
    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
    public class EntityProfile
    {
    	public EntityProfile()
    	{   // Création des la relation many to many
    		ListUtilisateurs = new THashSet<EntityUtilisateur>();
    		ProfileID = 0;
    	}
     
    	public Int64                    ProfileID               { get; set; }
     
    	/// <summary>
    	/// Permet de faire une relation de type many to many entre les utilisateurs et leurs profils.
    	/// </summary>
    	/// <value>Liste des utilisateurs contenant ce profil.</value>
    	public ICollection<EntityUtilisateur> ListUtilisateurs  { get; set; }
    }
    Table des utilisateurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class EntityUtilisateur : IDataErrorInfo
    {
    	public EntityUtilisateur()
    	{   // Création des la relation many to many
    		UtilisateurID = 0;
    		ListProfiles = new THashSet<EntityProfile>();
    	}
     
    	public Int64                    UtilisateurID               { get; set; }
     
    	public ICollection<EntityProfile> ListProfiles              { get; set; }
    }
    Et enfin le provider des utilisateurs.
    Je sais tout faire avec : trouver un utilisateur, trouver un utilisateur avec tous ses profiles, créer un utilisateur, détruire un utilisateur.
    Mais lorsque je mets à jour la liste des profiles d'un utilisateur là plus rien ne marche, j'ai essayé plein de choses et rien n'y fait, impossible de modifier cette table intermédiaire qui contient les liens entre les deux tables !
    Soit ça ne fait rien, soit ça plante, soit ça me supprime le profile au lieu de supprimer le lien (la liste des profiles est fixe).
    Petite chose à savoir : la liste des profiles est fixes, il ne faut donc jamais les supprimer, juste retirer le lien entre la table profile et la table utilisateur.
    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
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
        /// <summary>
        /// Provider utilisé pour accéder aux utilisateurs.
        /// </summary>
        public class UtilisateurProvider
        {
            /// <summary>
            /// Constructeur par défaut.
            /// </summary>
            public UtilisateurProvider()
            {
            }
     
            /// <summary>
            /// Récupérer la liste des utilisateurs.
            /// </summary>
            /// <returns>La liste des utilisateurs.</param>
            public ObservableCollection<EntityUtilisateur> GetUsers()
            {
                ObservableCollection<EntityUtilisateur> lstEntityUser = new ObservableCollection<EntityUtilisateur>();
     
                using(DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                {
                    lstEntityUser = context.Utilisateurs.ToObservableCollection();
                }
     
                return lstEntityUser;
            }
     
            /// <summary>
            /// Récupérer la liste des utilisateurs.
            /// </summary>
            /// <returns>La liste des utilisateurs.</param>
            public ObservableCollection<EntityUtilisateur> GetUsersAndProfiles()
            {
                ObservableCollection<EntityUtilisateur> lstEntityUsersAndProfiles = new ObservableCollection<EntityUtilisateur>();
     
                using(DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                {
                    lstEntityUsersAndProfiles = context.Utilisateurs.Include(x => x.ListProfiles).ToObservableCollection();
                }
     
                return lstEntityUsersAndProfiles;
            }
     
            /// <summary>
            /// Trouver un utilisateur par son nom.
            /// </summary>
            /// <param name="_strLogin">Login de l'utilisateur à rechercher.</param>
            /// <returns>Un utilisateur si trouvé, null sinon.</param>
            public EntityUtilisateur FindUserByLogin(String _strLogin)
            {
                EntityUtilisateur user = null;
                List<EntityUtilisateur> lstEntityUsers;
     
                using(DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                {   // Exécuter la requête de recherche...
                    lstEntityUsers = context.Utilisateurs.Where(x => x.Login == _strLogin).ToList();
                }
     
                if (lstEntityUsers.Count == 1)
                {
                    user = lstEntityUsers[0];
                }
                else if (lstEntityUsers.Count > 1)
                {   // Plusieurs login avec le même nom, ce n'est pas normal !
                    // Et lequel prendre ? Problème de sécurité ? Ce n'est pas admis !!
                    Logger.FatalLogger.Fatal(String.Format("Le nom de l'utilisateur {0} est présent {1} fois, une seule fois est autorisé !",_strLogin,lstEntityUsers.Count));
                }
     
                return user;
            }
     
            /// <summary>
            /// Trouver un utilisateur par son Identifiant.
            /// </summary>
            /// <param name="_strLogin">Login de l'utilisateur à rechercher.</param>
            /// <returns>Un utilisateur si trouvé, null sinon.</param>
            public EntityUtilisateur FindUserByID(Int64 _id,bool _bWithProfiles)
            {
                EntityUtilisateur user = null;
                List<EntityUtilisateur> lstEntityUsers;
     
                using(DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                {   // Exécuter la requête de recherche...
                    lstEntityUsers = _bWithProfiles
                        ? context.Utilisateurs.Where(x => x.UtilisateurID == _id).Include(x => x.ListProfiles).ToList()
                        : context.Utilisateurs.Where(x => x.UtilisateurID == _id).ToList();
                }
     
                if (lstEntityUsers.Count == 1)
                {
                    user = lstEntityUsers[0];
                }
                else if (lstEntityUsers.Count > 1)
                {   // Plusieurs login avec le même nom, ce n'est pas normal !
                    // Et lequel prendre ? Problème de sécurité ? Ce n'est pas admis !!
                    Logger.FatalLogger.Fatal(String.Format("L'utilisateur ayant pour ID = {0} est présent {1} fois, une seule fois est autorisé !",_id,lstEntityUsers.Count));
                }
     
                return user;
            }
     
            /// <summary>
            /// Vérifier la validité du login / mot de passe.
            /// </summary>
            /// <param name="_strLogin">Login de l'utilisateur.</param>
            /// <param name="_strPassword">Mot de passe utilisateur (en clair), utilise un hash MD5 pour vérifier avec ce qui est stocké en base.</param>
            /// <returns>null si l'utilisateur n'existe pas, true si le couple login / mot de passe est correct, false sinon.</param>
            public bool? IsLoginValid(string _strLogin,string _strPassword)
            {
                bool ?bRet = null;
     
                EntityUtilisateur user = FindUserByLogin(_strLogin);
                if (user != null)
                {
                    bRet = WPFExtToolkit.Tools.VerifyMd5Hash(_strPassword,user.MotPasse);
                }
     
                return bRet;
            }
     
            /// <summary>
            /// Créer une entité de type utilisateur dans la BDD
            /// </summary>
            /// <param name="_oProfile">Entité à ajouter dans la base de données. Est modifié par cet appel (ID mis à jour).</param>
            public bool Create(EntityUtilisateur _oUser)
            {
                using (DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                {
                    foreach(EntityProfile profile in _oUser.ListProfiles)
                    {
                        profile.ListUtilisateurs.Add(_oUser);
                        context.Profiles.Attach(profile);       // profile is in state Unchanged now
                    }
                    context.Utilisateurs.Add(_oUser);
                    return context.SaveChanges() > 0;
                }
            }
     
            /// <summary>
            /// Mise à jour d'une entité de type utilisateur dans la BDD
            /// </summary>
            /// <param name="_oUser">Utilisateur à mettre à jour.</param>
            /// <returns>true if correctly updated, false else.</returns>
            public bool Update(EntityUtilisateur _oUser)
            {
                try
                {
                    var dbUser = FindUserByID(_oUser.UtilisateurID,true);
     
                    //if (dbUser != null)
                    {
                        using (DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                        {
                            var user = context.Entry(_oUser);
    /*
                            foreach (var profile in user.Entity.ListProfiles)
                            {
                                profile.ListUtilisateurs.Add(_oUser);
                                var toto = context.Entry(profile);
                                toto.State = EntityState.Deleted;
                                //context.Profiles.Attach(profile);       // profile is in state Unchanged now
                                //int h =0;
                                //++h;
                            }
    */
     
                            // Supprimer les profiles qui ne sont plus assignés à cet utilisateur
                            // Utilise WPFExtToolkit.GeneralExtensions pour tester l'égalité uniquement sur le champ ProfileID
                            foreach (var profileToDelete in dbUser.ListProfiles.Except(_oUser.ListProfiles,z => z.ProfileID))
                            {
                                var itemToRemove = profileToDelete.ListUtilisateurs.SingleOrDefault(profile => profile.UtilisateurID == _oUser.UtilisateurID);
                                if (itemToRemove != null)
                                {
                                    profileToDelete.ListUtilisateurs.Remove(itemToRemove);
                                }
     
                                itemToRemove = profileToDelete.ListUtilisateurs.SingleOrDefault(profile => profile.UtilisateurID == _oUser.UtilisateurID);
                                if (itemToRemove != null)
                                {
                                    profileToDelete.ListUtilisateurs.Remove(itemToRemove);
                                }
     
                                context.Profiles.Attach(profileToDelete);       // profile is in state Unchanged now
                                context.Entry(profileToDelete).State =  EntityState.Modified;
                                //context.Profiles.Remove(profileToDelete); <-- Supprime le profile
                            }                            
    /*
     
                                context.Profiles.Local.
                                context.Profiles.ForEach(s => s.).
                                context.Utilisateurs.
                                context.Profiles.Remove(profileToDelete);
                                //user.Entity.ListProfiles.Remove(profileToDelete);
    */
     
                            user.State = EntityState.Modified;
                            return context.SaveChanges() > 0;
                        }
                    }
                    return false;
    /*
                try
                {
                    var dbUser = FindUserByID(_oUser.UtilisateurID,true);
     
                    using (DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                    {
                        var user = context.Entry(_oUser);
                        foreach (var profile in dbUser.ListProfiles)
                        {
                            bool bFind = false;
     
                            foreach (var profile2 in user.Entity.ListProfiles)
                            {
                                if (profile.ProfileID == profile2.ProfileID)
                                {
                                    bFind = true;
                                    break;
                                }
                            }
                            if (!bFind)
                            {
                                context.Profiles.(profile);
                            }
                        }
                        foreach (var profile in user.Entity.ListProfiles)
                        {
                            bool bFind = false;
     
                            foreach (var profile2 in  dbUser.ListProfiles)
                            {
                                if (profile.ProfileID == profile2.ProfileID)
                                {
                                    bFind = true;
                                    break;
                                }
                            }
                            if (!bFind)
                            {
                                context.Profiles.Attach(profile);
                            }
                        }
     
                        user.State = EntityState.Modified;
                        return context.SaveChanges() > 0;
                    }
    */
    /*
                        for 
     
                        var lstProfilesToDelete = dbUser.ListProfiles.Except(_oUser.ListProfiles).ToList();
                        var lstProfilesToAdd    = _oUser.ListProfiles.Except(dbUser.ListProfiles).ToList();
     
                        lstProfilesToAdd.ForEach(cs => user.Entity.ListProfiles.Add(cs));
                        lstProfilesToDelete.ForEach(cs => user.Entity.ListProfiles.Remove(cs));
     
                        user.Entity.Login = _oUser.Login;
                        user.Entity.MotPasse = _oUser.MotPasse;
                        user.Entity.Nom = _oUser.Nom;
                        user.Entity.Prenom = _oUser.Prenom;
                        //user.State = EntityState.;
    */
                }
                catch
                {
                    throw;
                }
            }
     
            /// <summary>
            /// Supprime un utilisateur à partir de son ID.
            /// </summary>
            /// <param name="_idUser">ID de l'utilisateur.</param>
            /// <returns>Nombre d'utilisateurs supprimés (0 si non trouvé).</returns>
            public bool Delete(Int64 _idUser)
            {
                using (DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                {
                    var requestDelete = context.Utilisateurs.Where(user => user.UtilisateurID == _idUser);
                    foreach (var request in requestDelete.ToList())
                    {
                        context.Utilisateurs.Remove(request);
                    }
                    return context.SaveChanges() == 1;
                }
            }
     
            /// <summary>
            /// Liste des profiles de cet utilisateur.
            /// </summary>
            public DbSet<EntityUtilisateur> Profiles                        { get; set; }
        }

  2. #2
    Membre confirmé

    Inscrit en
    Février 2007
    Messages
    253
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Février 2007
    Messages : 253
    Par défaut
    Bon, j'ai trouvé la réponse :
    Bon, ce code utilise d'autres classes, je ne vais pas tout donner ici (tout ce qui est Tools.* )
    => Copie profondes
    => Clone profond
    => Traitement sur listes (Except par exemple) sur critère
    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
            /// <summary>
            /// Mise à jour d'une entité de type utilisateur dans la BDD
            /// </summary>
            /// <param name="_oUser">Utilisateur à mettre à jour.</param>
            /// <returns>true if correctly updated, false else.</returns>
            public bool Update(EntityUtilisateur _oUser)
            {
                try
                {
                    using (DatabaseManagerContext context = DatabaseManagerContext.CreateInstance())
                    {
                        // 1 - Récupérer l'utilisateur dans la base de données
                        var existingUser = context.Utilisateurs.Include(x => x.ListProfiles).Where(s => s.UtilisateurID == _oUser.UtilisateurID).FirstOrDefault<EntityUtilisateur>();
     
                        // 2 - Trouver les profiles détruits depuis la collection de l'utilisateur en calculant la liste des profiles en base moins
                        //     la liste des profiles de l'utilisateur passé en paramètre
                        var deletedProfiles = existingUser.ListProfiles.Except(_oUser.ListProfiles, profile => profile.ProfileID).ToList<EntityProfile>();
     
                        // 3 - Trouver la liste des profiles ajoutés en calculant la liste des profiles de l'utilisateur moins la liste de profiles
                        //     de l'utilisateur existant déjà en base
                        var addedProfiles = _oUser.ListProfiles.Except(existingUser.ListProfiles,profile => profile.ProfileID).ToList<EntityProfile>();
     
                        // 4 - Supprimer les profiles retiré de la liste des profiles dans la base de données
                        deletedProfiles.ForEach(c => existingUser.ListProfiles.Remove(c));
     
                        // 5 - Ajouter les nouveaux profiles
                        foreach(EntityProfile profile in addedProfiles)
                        {
                            // 6 - Attacher chaque profile car il vient du client en tant qu'état détaché dans un scénario déconnecté
                            if (context.Entry(profile).State == EntityState.Detached)
                            {
                                context.Profiles.Attach(profile);
                            }
     
                            // 7 - Ajouter le profile à la collection des profiles de l'utilisateur
                            existingUser.ListProfiles.Add(profile);
                        }
     
                        // 8 - Mettre à jour les champs de l'utilisateur qui ont peut-être aussi été modifiés
                        String strListProfileFunctionName = "ListProfiles";
                        if (typeof(EntityUtilisateur).GetProperty(strListProfileFunctionName) == null)
                        {
                            Logger.FatalLogger.Fatal(String.Format("La propriété {0} de la classe {1} n'existe plus, veuillez revoir le code source !",strListProfileFunctionName,typeof(EntityUtilisateur).Name));
                        }
                        else
                        {   // Assigner tous les champs de l'utilisateur sauf la liste des profiles qui a déjà été assignée
                            Tools.AssignObject(_oUser,existingUser,new List<String>() { strListProfileFunctionName });
                            //context.Entry(existingUser).State = EntityState.Modified; <-- Pas nécéssaire
                        }
     
                        // 9 - Sauvegarder les changement, qui ne va refléter que les changement que dans la table intermédiaire des deux tables Utilisateurs et Profiles
                        //     Et l'utilisateur lui-même
                        return context.SaveChanges() > 0;
                    }
                }
                catch
                {
                    throw;
                }
            }
    Dans le OnModel Creating :
    J'ai modifié .WithMany(c => c.ListUtilisateurs) par .WithMany() pour que la liste des profiles n'aient plus de lien avec les utilisateurs.
    Ça reste du many to many mais avec une liste que d'un seul côté.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
            protected override void OnModelCreating(DbModelBuilder _modelBuilder)
            {
                // Ajout de la table intermédiaire créée par Entity Framework pour lier les
                // utilisateurs et les profils. Sans ce code, le nom de la table générée est
                // trop long et la création plante
                _modelBuilder.Entity<EntityUtilisateur>().HasMany(p => p.ListProfiles)
                                                         .WithMany()
                                                         .Map(manyToMany => manyToMany
                                                         .ToTable("DMUtilisateurProfiles", "GDD")
                                                         .MapLeftKey("FKUtilisateurID")
                                                         .MapRightKey("FKProfileID"));
     
                base.OnModelCreating(_modelBuilder);
            }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [trigger]Probleme d'update sur une table
    Par AlternantOracle dans le forum PL/SQL
    Réponses: 5
    Dernier message: 25/02/2010, 15h11
  2. [AC-2003] Requête UPDATE sur une table sans relation
    Par SIGER_971 dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 09/07/2009, 09h02
  3. [SQL] update sur une table de la relation
    Par comme de bien entendu dans le forum Requêtes et SQL.
    Réponses: 8
    Dernier message: 07/01/2009, 14h24
  4. Update sur une Table Oracle
    Par faressam dans le forum VBScript
    Réponses: 3
    Dernier message: 18/09/2008, 10h01
  5. UPDATE sur une table (mot réservé)
    Par calp25 dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 20/04/2008, 22h33

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