L’introduction de la contrainte FOREIGN KEY peut entraîner des cycles ou plusieurs chemins en cascade – pourquoi?

J’ai lutté avec ça pendant un moment et je n’arrive pas à comprendre ce qui se passe. J’ai une entité de carte qui contient des côtés (généralement 2) – et les deux cartes et les côtés ont une étape. J’utilise les migrations EF Codefirst et les migrations échouent avec cette erreur:

L’introduction de la contrainte FOREIGN KEY ‘FK_dbo.Sides_dbo.Cards_CardId’ sur la table ‘Sides’ peut provoquer des cycles ou plusieurs chemins en cascade. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modifiez d’autres contraintes FOREIGN KEY.

Voici mon entité de carte :

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é latérale :

 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 ssortingng Title { get; set; } Stage(TimeSpan span, ssortingng title) { this.span = span; this.Title = title; } public TimeSpan Span { get { return span; } } } 

Ce qui est étrange, c’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 correctement. Si j’ouvre SSMS et que je regarde les tables, je peux voir que Stage_StageId a été ajouté aux Cards (comme prévu / souhaité), mais Sides ne contient aucune référence à Stage (non attendu).

Si j’ajoute alors

  [Required] [ForeignKey("StageId")] public virtual Stage Stage { get; set; } public int StageId { get; set; } 

À ma classe Side, je vois la colonne StageId ajoutée à ma table Side .

Cela fonctionne, mais maintenant, tout au long de mon application, toute référence à Stage contient un SideId , ce qui est dans certains cas totalement hors de propos. Je voudrais juste donner à mes entités Card et Side une propriété Stage basée sur la classe Stage ci-dessus sans polluer la classe de scène avec des propriétés de référence si possible … qu’est-ce que je fais mal?

    Stage donné que Stage est requirejs , toutes les relations un-à-plusieurs où Stage est impliqué auront la suppression en cascade activée par défaut. Cela signifie que si vous supprimez une entité Stage

    • la suppression se répercutera directement sur le Side
    • la suppression se répercutera directement sur la Card et, parce que Card et Side ont une relation un-à-plusieurs requirejse avec la suppression en cascade activée à nouveau par défaut, elle passera ensuite d’une Card à l’ Side cascade.

    Vous disposez donc de deux chemins de suppression en cascade de Stage à Side – ce qui provoque l’exception.

    Vous devez soit rendre la Stage facultative dans au moins une des entités (c’est-à-dire supprimer l’atsortingbut [Required] des propriétés de la Stage ) ou désactiver la suppression en cascade avec l’API Fluent (impossible avec les annotations de données):

     modelBuilder.Entity() .HasRequired(c => c.Stage) .WithMany() .WillCascadeOnDelete(false); modelBuilder.Entity() .HasRequired(s => s.Stage) .WithMany() .WillCascadeOnDelete(false); 

    J’avais une table qui avait une relation circulaire avec les autres et je recevais la même erreur. Il s’agit de la clé étrangère qui n’était pas nullable. Si la clé n’est pas nullable, l’object associé doit être supprimé et les relations circulaires ne le permettent pas. Donc, utilisez la clé étrangère nullable.

     [ForeignKey("StageId")] public virtual Stage Stage { get; set; } public int? StageId { get; set; } 

    J’avais cette erreur pour beaucoup d’entités lorsque je passais d’un modèle EF7 à une version EF6. Je ne voulais pas passer par chaque entité une par une, alors j’ai utilisé:

     builder.Conventions.Remove(); builder.Conventions.Remove(); 

    Quelqu’un se demande comment faire dans le kernel EF:

      protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys())) { relationship.DeleteBehavior = DeleteBehavior.Ressortingct; } ..... rest of the code..... 

    Vous pouvez définir cascadeDelete sur false ou true (dans votre méthode de migration Up ()). Dépend de vos besoins

     AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false); 

    J’ai eu ce problème aussi, je l’ai résolu instantanément avec cette réponse d’un fil similaire

    Dans mon cas, je ne voulais pas supprimer l’enregistrement dépendant lors de la suppression de la clé. Si c’est le cas dans votre situation, remplacez simplement la valeur booléenne dans la migration par false:

     AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false); 

    Les chances sont, si vous créez des relations qui lancent cette erreur de compilation, mais que vous voulez conserver la suppression en cascade; vous avez un problème avec vos relations.

    Cela semble étrange et je ne sais pas pourquoi, mais dans mon cas, cela se produisait parce que mon ConnectionSsortingng utilisait “.” dans l’atsortingbut “source de données”. Une fois que je l’ai changé pour “localhost”, il a fonctionné comme un charme. Aucun autre changement n’était nécessaire.

    Dans .NET Core j’ai changé l’option onDelete en ReferencialAction.NoAction

      constraints: table => { table.PrimaryKey("PK_Schedule", x => x.Id); table.ForeignKey( name: "FK_Schedule_Teams_HomeId", column: x => x.HomeId, principalTable: "Teams", principalColumn: "Id", onDelete: ReferentialAction.NoAction); table.ForeignKey( name: "FK_Schedule_Teams_VisitorId", column: x => x.VisitorId, principalTable: "Teams", principalColumn: "Id", onDelete: ReferentialAction.NoAction); }); 

    Les réponses existantes sont excellentes. Je voulais juste append que j’ai rencontré cette erreur pour une raison différente. Je voulais créer une migration EF initiale sur une firebase database existante mais je n’ai pas utilisé le drapeau -IgnoreChanges et appliqué la commande Update-Database sur une firebase database vide (également sur l’échec existant).

    Au lieu de cela, j’ai dû exécuter cette commande lorsque la structure de firebase database actuelle est la structure actuelle:

     Add-Migration Initial -IgnoreChanges 

    Il y a probablement un vrai problème dans la structure de la firebase database mais sauve le monde un pas à la fois …

    J’ai corrigé cela. Lorsque vous ajoutez la migration, dans la méthode Up (), il y aura une ligne comme celle-ci:

    .ForeignKey (“dbo.Members”, t => t.MemberId, cascadeDelete: True)

    Si vous supprimez simplement la cascadeDelete à la fin, cela fonctionnera.

    Juste pour la documentation, à quelqu’un qui vient sur le futur, cette chose peut être aussi simple que cela, et avec cette méthode, vous pouvez faire une méthode qui désactive une fois, et vous pouvez accéder à votre méthode normalement

    Ajoutez cette méthode à la classe de firebase database de contexte:

     protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove(); } 

    Dans .NET Core, j’ai joué avec toutes les réponses supérieures – mais sans succès. J’ai fait beaucoup de changements dans la structure de la firebase database et à chaque fois, j’ai ajouté une nouvelle migration en essayant de update-database à update-database , mais j’ai reçu la même erreur.

    Ensuite, j’ai commencé à remove-migration un par un jusqu’à ce que la console du gestionnaire de paquets me fasse exception:

    La migration ‘20170827183131 _ ***’ a déjà été appliquée à la firebase database

    Après cela, j’ai ajouté avec succès une nouvelle migration ( add-migration ) et une nouvelle update-database

    Donc, ma suggestion serait la suivante: effacer toutes vos migrations temporaires, jusqu’à votre état actuel de la firebase database.

    Aucune des solutions susmentionnées n’a fonctionné pour moi. Ce que je devais faire était d’utiliser un int nul (int?) Sur la clé étrangère qui n’était pas requirejse (ou une clé de colonne non null), puis de supprimer certaines de mes migrations.

    Commencez par supprimer les migrations, puis essayez le nullable int.

    Le problème était à la fois une modification et une conception du modèle. Aucun changement de code n’était nécessaire.