Je lutte avec ça depuis un moment et je n'arrive pas à comprendre ce qui se passe. J'ai une entité Carte qui contient des côtés (généralement 2) - et les 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 de cascade. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modifiez d'autres contraintes FOREIGN KEY.
Voici mon entité Carte :
public class Card
{
public Card()
{
Sides = new Collection<Side>();
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int CardId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
[ForeignKey("CardId")]
public virtual ICollection<Side> 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<Stage> 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; } }
}
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 a réussi. Si j'ouvre SSMS et regarde les tableaux, je peux voir qu'il Stage_StageId
a été ajouté à Cards
(comme prévu / souhaité), mais Sides
ne contient aucune référence à Stage
(non attendu).
Si j'ajoute ensuite
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
Pour ma classe Side, je vois une StageId
colonne ajoutée à ma Side
table.
Cela fonctionne, mais maintenant tout au long de mon application, toute référence à Stage
contient un SideId
, qui est dans certains cas totalement hors de propos. Je voudrais juste donner à mes entités Card
et Side
une Stage
propriété basée sur la classe Stage ci-dessus sans polluer la classe Stage avec des propriétés de référence si possible ... que fais-je de mal?
Side
classe, ajoutez un entier nul et supprimez l'[Required]
attribut =>public int? CardId { get; set; }
DeleteBehavior.Restrict
ouDeleteBehavior.SetNull
.Réponses:
Parce que cela
Stage
est requis , 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 uneStage
entitéSide
Card
et parce queCard
etSide
avec une relation un-à-plusieurs requise avec la suppression en cascade activée à nouveau par défaut, elle sera ensuite mise en cascade deCard
àSide
Ainsi, vous avez deux chemins de suppression en cascade de
Stage
àSide
- ce qui provoque l'exception.Vous devez soit rendre l'
Stage
option facultative dans au moins une des entités (c'est-à-dire supprimer l'[Required]
attribut desStage
propriétés) ou désactiver la suppression en cascade avec l'API Fluent (impossible avec les annotations de données):la source
Stage
. Les autres relations restent inchangées.Stage
suppression à cascade à laSide
fois directement et via unCard
J'avais une table qui avait une relation circulaire avec les autres et j'obtenais la même erreur. Il s'avère qu'il s'agit de la clé étrangère qui n'était pas annulable. Si la clé n'est pas annulable, l'objet lié doit être supprimé et les relations circulaires ne le permettent pas. Utilisez donc une clé étrangère nullable.
la source
int?
au lieu de laint
laisser nullable.Quiconque se demande comment le faire dans EF core:
la source
builder.HasOne(x => x.Stage).WithMany().HasForeignKey(x => x.StageId).OnDelete(DeleteBehavior.Restrict);
builder _ .Entity<TEntity>() _
précèdeHasOne()
peut être appelé ...IEntityTypeConfiguration<T>
. Je ne me souviens pas avoir vu labuilder.Entity<T>
méthode ces jours-là, mais je peux me tromper. Néanmoins, ils fonctionneront tous les deux :)J'obtenais cette erreur pour de nombreuses entités lorsque je migrais d'un modèle EF7 vers une version EF6. Je ne voulais pas avoir à passer par chaque entité une par une, alors j'ai utilisé:
la source
Vous pouvez définir cascadeDelete sur false ou true (dans votre méthode de migration Up ()). Dépend de votre condition.
la source
UP
méthode peut être modifiée par des opérations externes.Dans .NET Core, j'ai changé l'option onDelete en ReferencialAction.NoAction
la source
J'ai aussi eu ce problème, 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 clé. Si c'est le cas dans votre situation, changez simplement la valeur booléenne de la migration en false:
Il y a de fortes chances que si vous créez des relations qui génèrent cette erreur de compilation mais que vous souhaitez conserver la suppression en cascade; vous avez un problème avec vos relations.
la source
J'ai corrigé ça. Lorsque vous ajoutez la migration, dans la méthode Up (), il y aura une ligne comme celle-ci:
Si vous supprimez simplement le cascadeDelete de la fin, cela fonctionnera.
la source
Juste à des fins de documentation, pour quelqu'un qui vient dans le futur, cette chose peut être résolue aussi simple que cela, et avec cette méthode, vous pouvez faire une méthode qui s'est désactivée une fois, et vous pouvez accéder à votre méthode normalement
Ajoutez cette méthode à la classe de base de données de contexte:
la source
Cela semble bizarre et je ne sais pas pourquoi, mais dans mon cas, cela se produisait parce que mon ConnectionString utilisait "." dans l'attribut "source de données". Une fois que je l'ai changé en "localhost", cela a fonctionné comme un charme. Aucun autre changement n'était nécessaire.
la source
Dans .NET Core, j'ai joué avec toutes les réponses supérieures - mais sans succès. J'ai beaucoup changé la structure de la base de données et à chaque fois j'ai ajouté une nouvelle migration essayant de
update-database
, mais reçu la même erreur.Ensuite, j'ai commencé
remove-migration
un par un jusqu'à ce que la console du gestionnaire de packages me lance une exception:Après cela, j'ai ajouté une nouvelle migration (
add-migration
) et j'aiupdate-database
réussiDonc, ma suggestion serait: effacez toutes vos migrations temporaires, jusqu'à votre état actuel de la base de données.
la source
Les réponses existantes sont excellentes. Je voulais juste ajouter que j'ai rencontré cette erreur pour une raison différente. Je voulais créer une migration EF initiale sur une base de données existante mais je n'ai pas utilisé les -IgnoreChanges indicateur et appliqué la commande Update-Database sur une base de données vide (également sur les échecs existants).
Au lieu de cela, j'ai dû exécuter cette commande lorsque la structure de base de données actuelle est la suivante:
Il y a probablement un vrai problème dans la structure de la base de données mais sauvez le monde une étape à la fois ...
la source
Le moyen le plus simple consiste à, éditez votre fichier de migration
(cascadeDelete: true)
dans(cascadeDelete: false)
puis après affecter la commande Update-Database dans votre console du gestionnaire de package. Sinon, vérifiez votre historique de migration précédent, copiez ces éléments, collez-les dans votre dernier fichier de migration, puis faites la même chose. cela fonctionne parfaitement pour moi.la source
Lorsque votre migration échoue, deux options vous sont proposées: 'Introduction de la contrainte FOREIGN KEY' FK_dbo.RecommendedBook_dbo.Department_DepartmentID 'sur la table' RecommendedBook 'peut provoquer des cycles ou plusieurs chemins de cascade. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modifiez d'autres contraintes FOREIGN KEY. Impossible de créer une contrainte ou un index. Voir les erreurs précédentes. '
Voici un exemple d'utilisation de la «modification d'autres contraintes FOREIGN KEY» en définissant «cascadeDelete» sur false dans le fichier de migration, puis exécutez «update-database».
la source
Aucune des solutions susmentionnées n'a fonctionné pour moi. Ce que je devais faire était d'utiliser un int nullable (int?) Sur la clé étrangère qui n'était pas requise (ou pas une clé de colonne non nulle), 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 la conception du modèle. Aucun changement de code n'était nécessaire.
la source
Rendez vos attributs de clé étrangère nullables. Ça marchera.
la source