Bonjour,
Je voudrais être capable de supprimer des orphelins dans une relation 1-*.
Si j'en crois les différents tuto, cela à l'air d'être enfantin à réaliser. Tuto
Dans ma base, j'ai une table Client et une table SuiviClient, laquelle à une clé étrangère non nullable Client_Id pointant sur la clé primaire de la table Client.
Mon mappage ressemble à cela :
Toutefois, quand je retire un suivi de la liste (et que le client associé devient null). La base de donnée me génère une exception me disant que la clé étrangère interdit les valeurs null.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 modelBuilder.Entity<Client>() .HasMany(c => c.ListeSuivi) .WithRequired() .HasForeignKey(c => c.Client_Id) .WillCascadeOnDelete(); modelBuilder.Entity<SuiviClient>() .HasKey(s => new { s.Id, s.Client_Id }) .Property(s => s.Id) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Soit, je suis d'accord, mais je m'attendais à ce que EF me supprime le suivi plutôt que d'essayer de le modifier comme expliqué dans le tuto plus haut.
Ou est ce que je m'y prend mal ?
Edit :
Je reviens vers vous après avoir fait quelque test. J'ai essayé sur un petit projet de mettre en scène mon problème. Il se trouve que la gestion des orphelins est bien correctement géré à l'aide de .HasKey(s => new { s.Id, s.Client_Id }).
Le soucis viens du fait qu'en réalité j'utilise de l'héritage avec un model Table Par Classe. J'ai donc SuiviClient qui hérite de la classe Suivi. Coté base de donnée, j'ai une table Suivi et une table SuiviClient.
La table SuiviClient à une clé étrangère de son ID vers l'ID de la table Suivi.
Dans ce cas la, je n'arrive plus à faire fonctionner la suppréssion des orphelins.
Edit 2 :
Un exemple concret :
- Cas 1 : Sans héritage, le ContactClient est bien supprimé au moment du savechange après avoir supprimer la relation au client
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 public class Client { public Client() { Contacts = new List<ContactClient>(); } [Key, Column(Order = 1)] public int ID { get; set; } public virtual string Nom { get; set; } public virtual List<ContactClient> Contacts { get; set; } } [Table("ContactClients")] public class ContactClient { [Key, Column(Order = 1)] public virtual int ID { get; set; } public virtual string Nom { get; set; } [Key, Column(Order = 2)] public int Client_ID { get; set; } [ForeignKey("Client_ID")] public virtual Client Client { get; set; } } public class Context : DbContext { public Context(string connectionString) : base(connectionString) { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Client>() .HasMany(c => c.Contacts) .WithRequired() .HasForeignKey(c => c.Client_ID) .WillCascadeOnDelete(); modelBuilder.Entity<ContactClient>(); base.OnModelCreating(modelBuilder); } } static void Main(string[] args) { try { Context context = new Context("TestAdhoc"); Client client = new Client() { Nom = "Hello" }; ContactClient contact = new ContactClient() { Nom = "World" }; client.Contacts.Add(contact); context.Set<Client>().Add(client); context.SaveChanges(); context.Dispose(); context = new Context("TestAdhoc"); client = context.Set<Client>().Single(c => c.Nom == "Hello"); client.Contacts.Remove(client.Contacts.Single(c => c.Nom == "World")); context.SaveChanges(); } catch(Exception e) { } }- Cas 2 : Avec héritage, le contactclient ne passe pas à l'état Deleted et le savechanges essaye d'insérer une valeur null dans la relation de clé étrangère vers le client ce qui génère une exception
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 public class Client { public Client() { Contacts = new List<ContactClient>(); } [Key, Column(Order = 1)] public int ID { get; set; } public virtual string Nom { get; set; } public virtual List<ContactClient> Contacts { get; set; } } public class Contact { [Key, Column(Order = 1)] public virtual int ID { get; set; } public virtual string Nom { get; set; } } [Table("ContactClients")] public class ContactClient : Contact { [Key, Column(Order = 2)] public int Client_ID { get; set; } [ForeignKey("Client_ID")] public virtual Client Client { get; set; } } public class Context : DbContext { public Context(string connectionString) : base(connectionString) { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Client>() .HasMany(c => c.Contacts) .WithRequired() .HasForeignKey(c => c.Client_ID) .WillCascadeOnDelete(); modelBuilder.Entity<Contact>(); modelBuilder.Entity<ContactClient>(); base.OnModelCreating(modelBuilder); } } static void Main(string[] args) { try { Context context = new Context("TestAdhoc"); Client client = new Client() { Nom = "Hello" }; ContactClient contact = new ContactClient() { Nom = "World" }; client.Contacts.Add(contact); context.Set<Client>().Add(client); context.SaveChanges(); context.Dispose(); context = new Context("TestAdhoc"); client = context.Set<Client>().Single(c => c.Nom == "Hello"); client.Contacts.Remove(client.Contacts.Single(c => c.Nom == "World")); context.SaveChanges(); } catch(Exception e) { } }
Je tiens vraiment à supprimer mes orphelins de manière propre et éviter le workaround dans mes repositories ...
Partager