Dans Entity Framework 7 lorsque j'essaie d'appliquer une migration, j'obtiens l'erreur
L'introduction de la contrainte FOREIGN KEY 'FK_ChangeOrder_User_CreatedByID' sur la table 'ChangeOrder' 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. Voir les erreurs précédentes.
Je sais que dans les anciennes versions d'Entity Framework, vous géreriez cela en ajoutant
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
au DbContext mais dans EF7 modelBuilder
ne semble pas avoir un .Conventions
et Google ne renvoie que les anciens EF 4 à EF 6.
Comment spécifier le ON DELETE NO ACTION
contrainte dans Entity Framework 7?
Edit: La réponse fournie par Oleg le fera apparemment par clé étrangère, mais je voudrais le faire globalement car il sera beaucoup plus facile d'utiliser une ligne de code pour le déclarer globalement, puis de le spécifier pour chaque code des centaines de relations que je finirai par avoir.
Edit 2: Code pour Oleg
public class ChangeOrder
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public Int16? ApprovedByID { get; set; }
public Byte ApprovalStatusID { get; set; }
public Int16 AssignedToID { get; set; }
public Int16 CreatedByID { get; set; }
public Byte CurrentStatusID { get; set; }
public DateTime? DateApproved { get; set; }
public DateTime? EndDate { get; set; }
public Byte ImpactID { get; set; }
public Byte PriorityID { get; set; }
public DateTime? StartDate { get; set; }
public Byte TypeID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string ReasonForChange { get; set; }
[ForeignKey("ApprovedByID")]
public User ApprovedBy { get; set; }
[ForeignKey("ApprovalStatusID")]
public ChangeApprovalStatus ApprovalStatus { get; set; }
[ForeignKey("AssignedToID")]
public User AssignedTo { get; set; }
[ForeignKey("CreatedByID")]
public User CreatedBy { get; set; }
[ForeignKey("ImpactID")]
public ChangeImpact Impact { get; set; }
[ForeignKey("PriorityID")]
public ChangePriority Priority { get; set; }
[ForeignKey("TypeID")]
public ChangeType ChangeType { get; set; }
[ForeignKey("CurrentStatusID")]
public ChangeStatus CurrentStatus { get; set; }
}
public class JobSightDBContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelbuilder)
{
base.OnModelCreating(modelbuilder);
}
DbSet<ChangeApprovalStatus> ChangeApprovalStatus { get; set; }
DbSet<ChangeImpact> ChangeImapct { get; set; }
DbSet<ChangeOrder> ChangeOrders { get; set; }
DbSet<ChangePriority> ChangePriorities { get; set; }
DbSet<ChangeStatus> ChangeStatus { get; set; }
DbSet<ChangeType> ChangeTypes { get; set; }
DbSet<User> Users { get; set; }
}
Après avoir creusé sur GitHub et travaillé avec un gars très patient de MS là-bas, la solution actuelle consiste à l'ajouter au DbContext
protected override void OnModelCreating(ModelBuilder modelbuilder)
{
foreach (var relationship in modelbuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
base.OnModelCreating(modelbuilder);
}
La construction
modelBuilder.Entity("myNamespace.Models.ChangeOrder", b =>
{
b.HasOne("myNamespace.Models.User")
.WithMany()
.HasForeignKey("CreatedByID")
.OnDelete(DeleteBehavior.Cascade);
});
will signifie créer FK_ChangeOrder_User_CreatedByID
avec REFERENCES [dbo].[User] ([CreatedByID]) ON DELETE CASCADE
. Il doit exister dans protected override void BuildModel(ModelBuilder modelBuilder)
de YourContextModelSnapshot.cs
Créé lors de la migration. Je ne suis pas sûr d'avoir bien compris votre question, mais je pense que vous devriez soit ajouter une telle construction à XXXModelSnapshot.cs
Soit supprimer une construction inutile, qui existe déjà ici.
MISE À JOUR: Je vois que vous avez le problème dans le modèle. Vous avez les propriétés suivantes dans
public Int16? ApprovedByID { get; set; }
public Int16 AssignedToID { get; set; }
public Int16 CreatedByID { get; set; }
// navigation properties
[ForeignKey("ApprovedByID")]
public User ApprovedBy { get; set; }
[ForeignKey("AssignedToID")]
public User AssignedTo { get; set; }
[ForeignKey("CreatedByID")]
public User CreatedBy { get; set; }
Par défaut, la migration essaie de définir DeleteBehavior.Cascade
Sur toutes les propriétés.
Vous pouvez remplacer le comportement en modifiant OnModelCreating
, qui définit le comportement DeleteBehavior.Restrict
Pour toutes les clés ou pour définir sur une seule clé le comportement DeleteBehavior.Cascade
Ou DeleteBehavior.SetNull
. Par exemple, le code ci-dessous utilise DeleteBehavior.Cascade
Sur CreatedByID
(ce qui crée ON DELETE CASCADE
Sur les clés étrangères) et DeleteBehavior.Restrict
Sur d'autres clés étrangères (non ON DELETE
Sur les clés étrangères):
public class JobSightDBContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelbuilder)
{
base.OnModelCreating(modelbuilder);
modelbuilder.Entity(typeof (ChangeOrder))
.HasOne(typeof (User), "ApprovedBy")
.WithMany()
.HasForeignKey("ApprovedByID")
.OnDelete(DeleteBehavior.Restrict); // no ON DELETE
modelbuilder.Entity(typeof (ChangeOrder))
.HasOne(typeof (User), "AssignedTo")
.WithMany()
.HasForeignKey("AssignedToID")
.OnDelete(DeleteBehavior.Restrict); // no ON DELETE
modelbuilder.Entity(typeof (ChangeOrder))
.HasOne(typeof (User), "CreatedBy")
.WithMany()
.HasForeignKey("CreatedByID")
.OnDelete(DeleteBehavior.Cascade); // set ON DELETE CASCADE
}
DbSet<ChangeApprovalStatus> ChangeApprovalStatus { get; set; }
DbSet<ChangeImpact> ChangeImapct { get; set; }
DbSet<ChangeOrder> ChangeOrders { get; set; }
DbSet<ChangePriority> ChangePriorities { get; set; }
DbSet<ChangeStatus> ChangeStatus { get; set; }
DbSet<ChangeType> ChangeTypes { get; set; }
DbSet<User> Users { get; set; }
}