Bonjour,

J'ai un problème avec Entity Framework dans le cadre de la suppression en cascade réalisée "manuellement" (dans mes fichiers de type nomfichierEntity.cs)

Je vais expliquer mon problème par un exemple:
Prenons le cas d'une garderie, j'ai une table A qui contient la liste des enfants qui sont inscrits dans la garderie.
J'ai ensuite dans mon application un plan d'un dortoir, les utilisateurs peuvent pour chaque enfant placer un marqueur sur le plan pour montrer quel est le lit attribué à l'enfant (chaque marqueur est mémorisé dans une table B, qui a une contrainte de clé étrangère sur A, en effet, on ne peut pas avoir de marqueur d'un enfant non inscrit à la garderie).

Mon problème à présent, je veux le comportement suivant:
- Si je supprime un marqueur, son enregistrement est retiré de la table B, mais l'enfant reste inscrit (persiste dans la table A).
- Si je résilie l'inscription d'un enfant, son enregistrement dans la table A est détruit, et par conséquent, il ne peut plus avoir de marqueur lui appartenant dans le dortoir, donc si un enregistrement en table B le concernant existait, il est supprimé (cascade classique...).

Ces 2 comportements fonctionnent très bien, à une exception près...
Si je fais "supprimer marqueur d'un enfant E", sauvegarder dans l'application (appel à submitchanges), puis "supprimer l'enfant E", tout va bien.
Si maintenant je fais la même séquence, mais sans sauvegarde au milieu (donc supprimer marqueur, puis supprimer l'enfant, puis sauvegarder), ça plante avec l'erreur suivante:

L’exception InvalidOperationException n’a pas été gérée par le code utilisateur
Un objet ayant la même clé existe déjà dans ObjectStateManager. ObjectStateManager ne peut pas assurer le suivi de plusieurs objets ayant la même clé.


Je ne comprends pas pourquoi et j'aimerais avoir votre aide

Dans le ViewModel (appli silverlight), voici les séquences de suppression (consécutives, pas de code entre, le tout étant encapsulé dans une ICommand déclenché par un bouton utilisateur):

le "supprimerEnfant" est un booléen dont l'état est déterminé par un parameter dans le xaml, (quand on veut supprimer, un popup apparait avec un radiobutton demandant si on veut supprimer l'enfant ou juste le marqueur, si c'est juste le marqueur, supprimerEnfant est à false)

// Suppression du marqueur uniquement:
if(!supprimerEnfant)
{
CollectionMarqueursEnfants.Remove(marqueurSupprimable);
// ObservableCollection de "marqueurEnfant" effectuant le rendu visuel des marqueurs dans l'application. MarqueurSupprimable est une propriété dont le set est fait ailleurs dans le ViewModel

contexteDomaine.MarqueursEnfants.Remove(marqueurSupprimable);
// Appelle le domainService pour supprimer le marqueurSupprimable dans la table B
}
// Suppression de l'enfant + marqueur:
else if (supprimerEnfant)
{
CollectionMarqueursEnfants.Remove(marqueurSupprimable);
ContexteDomaine.Enfants.Remove(marqueurSupprimable.Enfants.Single());
// La suppression dans la table A (enfants) va supprimer le marqueur par //cascade dans la table B
}

Maintenant concernant mes ma partie server de l'application, toujours dans le C# (pas le SGBD):

EnfantEntity.cs

public void DeleteEnfant(Enfant enf)
{

// D'abord la cascade supprimant le marqueur:
var listMarqueurs = this.ObjectContext.Marqueurs.where(
m => m.EnfantId == enf.Id).ToList();

foreach(var m in listMarqueurs)
DeleteMarqueur(m);

//Ensuite la suppression de l'enfant:
if(enf.EntityState != EntityState.Detached))
this.ObjectContext.ObjectStateManager.ChangeObjectState(enf, EntityState.Deleted);
else
{
this.ObjectContext.Enfants.Attach(enf);
this.ObjectContext.Enfants.DeleteObject(enf);
}

}


La suppression du marqueur est analogue à cette dernière méthode, sauf qu'il n'y a pas de cascade dans cette dernière:

MarqueurEntity.cs

public void DeleteMarqueur(Marqueur marq)
{
if(mar.EntityState != EntityState.Detached))
this.ObjectContext.ObjectStateManager.ChangeObjectState(marq, EntityState.Deleted);
else
{
this.ObjectContext.Marqueurs.Attach(marq);
this.ObjectContext.Marqueurs.DeleteObject(marq);
}

}

Est-ce que quelqu'un a une idée, je suis vraiment coincé sur ce point et j'apprécierais vraiment de l'aide?
Si on se pose la question, côté SGBD j'ai tenté de mettre en place une suppression en cascade via le placement des contraintes sur les clés étrangères... J'ai lu que c'était à éviter pour ne pas surcharger le SGBD... J'ai un problème de suppression multiples ou cycliques et ça ne peut se faire à cause d'autres tables non citées ici mais qui n'entrent pas en jeu dans le problème que je peine à résoudre!

En vous remerciant grandement