Je me suis débattu avec cela depuis un certain temps et je n'arrive pas à comprendre ce qui se passe. J'ai une entité Card qui contient des Sides (généralement 2) - et à la fois les Cards et les Sides ont un Stage. J'utilise des migrations EF Codefirst et les migrations échouent avec cette erreur :
L'introduction de la contrainte de clé étrangère 'FK_dbo.Sides_dbo.Cards_CardId' sur la table 'Sides' peut entraîner des cycles ou des chemins de cascade multiples. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modifiez d'autres contraintes de clé étrangère.
Voici mon entité Card :
public class Card
{
public Card()
{
Sides = new Collection();
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int CardId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
[ForeignKey("CardId")]
public virtual ICollection Sides { get; set; }
}
Voici mon entité Side :
public class Side
{
public Side()
{
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int SideId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
public int CardId { get; set; }
[ForeignKey("CardId")]
public virtual Card Card { get; set; }
}
Et voici mon entité Stage :
public class Stage
{
// Zero
public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
// Ten seconds
public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");
public static IEnumerable Values
{
get
{
yield return ONE;
yield return TWO;
}
}
public int StageId { get; set; }
private readonly TimeSpan span;
public string Title { get; set; }
Stage(TimeSpan span, string title)
{
this.span = span;
this.Title = title;
}
public TimeSpan Span { get { return span; } }
}
Le problème est que si j'ajoute ce qui suit à ma classe Stage :
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
La migration s'exécute avec succès. Si j'ouvre SSMS et regarde les tables, je peux voir que Stage_StageId
a été ajouté à Cards
(comme prévu/souhaité), cependant Sides
ne contient aucune référence à Stage
(pas attendue).
Si j'ajoute ensuite :
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
À ma classe Side, je vois que la colonne StageId
est ajoutée à ma table Side
.
Cela fonctionne, mais maintenant dans toute mon application, toute référence à Stage
contient un SideId
, qui est dans certains cas totalement inapproprié. J'aimerais simplement donner à mes entités Card
et Side
une propriété Stage
basée sur la classe Stage citée ci-dessus sans polluer la classe Stage avec des propriétés de référence si possible... que suis-je en train de faire de mal ?
8 votes
Désactiver la suppression en cascade en autorisant les valeurs nulles dans les références... donc dans la classe
Side
ajouter un entier Nullable et supprimer l'attribut[Required]
=>public int? CardId { get; set; }
4 votes
Dans EF Core, vous devez désactiver la suppression en cascade avec
DeleteBehavior.Restrict
ouDeleteBehavior.SetNull
.7 votes
La réponse acceptée est la seule réponse correcte. La question est : comment empêcher un chemin de cascade circulaire si je veux une relation obligatoire. Une seule instruction de mappage suffit. Donc, ne suggérez pas de rendre la relation optionnelle, ou pire, de modifier le fichier de migration généré (introduisant une divergence entre le modèle de base de données et le modèle conceptuel), ou pire encore, de désactiver toutes les suppressions en cascade.
0 votes
J'ai modifié le fichier de migration avant de faire update-database et j'ai remplacé cascade par noaction -> onDelete: ReferentialAction.NoAction. Cela a résolu le problème.