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; }
    }