J'ai trouvé un petit problème dans EntityFramework 6 et je ne sais pas si c'est quelque chose que j'ai mal fait.
Par défaut, je pense qu'il devrait être activé comme indiqué ici: http://www.entityframeworktutorial.net/code- first / cascade-delete-in-code-first.aspx
Mais j'ai trouvé des instances dans mon application où ce n'est pas le cas. J'ai ce modèle:
public class DatabaseContext : IdentityDbContext<User> { public DatabaseContext() : base("DefaultConnection") { Database.CommandTimeout = 900; Database.Log = s => Debug.WriteLine(s); Configuration.LazyLoadingEnabled = false; } public DbSet<Feed> Feeds { get; set; } public DbSet<Organisation> Organisations { get; set; } public DbSet<Category> Categories { get; set; } public DbSet<Criteria> Criteria { get; set; } public DbSet<Attribute> Attributes { get; set; } public DbSet<AttributeFormula> CriteriaForumlas { get; set; } public DbSet<AttributeType> AttributeTypes { get; set; } public DbSet<AttributeOperation> AttributeOperations { get; set; } public DbSet<Scenario> Scenarios { get; set; } public DbSet<Question> Questions { get; set; } public DbSet<Answer> Answers { get; set; } public DbSet<AnswerFormula> AnswerForumlas { get; set; } public DbSet<Quote> Quotes { get; set; } public DbSet<Claim> Claims { get; set; } public DbSet<Client> Clients { get; set; } public DbSet<RefreshToken> RefreshTokens { get; set; } public DbSet<Search> Searches { get; set; } public DbSet<Charge> Charges { get; set; } public DbSet<Exclusion> Exclusions { get; set; } public DbSet<Sortation> Sortations { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Table renames modelBuilder.Entity<Criteria>().ToTable("Criteria"); modelBuilder.Entity<IdentityRole>().ToTable("Roles"); modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles"); modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims"); modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins"); modelBuilder.Entity<ImageText>().ToTable("ImageText"); // One to One modelBuilder.Entity<Attribute>().HasOptional(m => m.Type).WithRequired(m => m.Attribute).WillCascadeOnDelete(false); modelBuilder.Entity<Attribute>().HasOptional(m => m.Operation).WithRequired(m => m.Attribute).WillCascadeOnDelete(false); modelBuilder.Entity<Answer>().HasOptional(m => m.Scenario).WithRequired(m => m.Answer).WillCascadeOnDelete(false); modelBuilder.Entity<Answer>().HasOptional(m => m.Criteria).WithMany().HasForeignKey(m => m.CriteriaId).WillCascadeOnDelete(false); // One to Many modelBuilder.Entity<Criteria>().HasMany(m => m.Attributes).WithRequired().HasForeignKey(m => m.CriteriaId).WillCascadeOnDelete(true); modelBuilder.Entity<IdentityRole>().HasMany(m => m.Users).WithRequired().HasForeignKey(m => m.RoleId).WillCascadeOnDelete(false); modelBuilder.Entity<Organisation>().HasMany(m => m.Feeds).WithRequired().HasForeignKey(m => m.OrganisationId).WillCascadeOnDelete(true); modelBuilder.Entity<Organisation>().HasMany(m => m.Users).WithRequired().HasForeignKey(m => m.OrganisationId).WillCascadeOnDelete(true); modelBuilder.Entity<Question>().HasMany(m => m.Answers).WithRequired(m => m.Question).HasForeignKey(m => m.QuestionId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Sortations).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Criteria).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Feeds).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Questions).WithOptional().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Quotes).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<User>().HasMany(m => m.Searches).WithRequired().HasForeignKey(m => m.UserId).WillCascadeOnDelete(true); modelBuilder.Entity<User>().HasMany(m => m.Charges).WithRequired().HasForeignKey(m => m.UserId).WillCascadeOnDelete(true); modelBuilder.Entity<Answer>().HasMany(m => m.Images).WithRequired().HasForeignKey(m => m.AnswerId).WillCascadeOnDelete(true); modelBuilder.Entity<Image>().HasMany(m => m.ImageText).WithRequired().HasForeignKey(m => m.ImageId).WillCascadeOnDelete(true); modelBuilder.Entity<Attribute>().HasMany(m => m.Formulas).WithRequired().HasForeignKey(m => m.AttributeId).WillCascadeOnDelete(true); modelBuilder.Entity<Answer>().HasMany(m => m.Formulas).WithRequired().HasForeignKey(m => m.AnswerId).WillCascadeOnDelete(true); // Create our primary keys modelBuilder.Entity<IdentityUserLogin>().HasKey(m => m.UserId); modelBuilder.Entity<IdentityRole>().HasKey(m => m.Id); modelBuilder.Entity<IdentityUserRole>().HasKey(m => new {m.RoleId, m.UserId}); modelBuilder.Entity<AttributeOperation>().HasKey(m => m.AttributeId); modelBuilder.Entity<AttributeType>().HasKey(m => m.AttributeId); modelBuilder.Entity<Scenario>().HasKey(m => m.AnswerId); } }
Il n'y avait pas de suppression en cascade pour les questions, j'ai donc mis à jour mon DbContext comme suit:
XXX
Et quand j'ai exécuté update-database
j'ai vu que la contrainte était maintenant correcte:
modelBuilder.Entity<Question>().HasMany(m => m.Answers).WithRequired(m => m.Question).HasForeignKey(m => m.QuestionId).WillCascadeOnDelete(true);
J'ai essayé pour supprimer une catégorie et une erreur s'est produite:
L'instruction DELETE était en conflit avec la contrainte REFERENCE
Après enquête, il se plaint au sujet du tableau Réponses . Voici les modèles Question et Answer :
ALTER TABLE [dbo].[Answers] WITH CHECK ADD CONSTRAINT [FK_dbo.Answers_dbo.Questions_QuestionId] FOREIGN KEY([QuestionId]) REFERENCES [dbo].[Questions] ([Id]) ON DELETE CASCADE GO
Le mappage ressemblait à ceci:
ALTER TABLE [dbo].[Answers] WITH CHECK ADD CONSTRAINT [FK_dbo.Answers_dbo.Questions_QuestionId] FOREIGN KEY([QuestionId]) REFERENCES [dbo].[Questions] ([Id]) GO
Mais si j'inspecte la contrainte, je vois ceci:
modelBuilder.Entity<Question>().HasMany(m => m.Answers).WithRequired(m => m.Question).HasForeignKey(m => m.QuestionId)
Ce qui me semble faux, je pense que cela devrait être:
public class Question : Key { public string CategoryId { get; set; } [Required, MaxLength(255)] public string Text { get; set; } [MaxLength(255)] public string AltText { get; set; } public int Order { get; set; } public int Priority { get; set; } public QuestionType Type { get; set; } public IList<Answer> Answers { get; set; } } public class Answer: Key { public int QuestionId { get; set; } public int? CriteriaId { get; set; } [Required] [MaxLength(255)] public string Text { get; set; } public int Order { get; set; } public int Priority { get; set; } [MaxLength(2083)] public string Image { get; set; } public Criteria Criteria { get; set; } public Question Question { get; set; } public Scenario Scenario { get; set; } public IList<AnswerFormula> Formulas { get; set; } public IList<Image> Images { get; set; } }
J'ai donc changé mon mappage pour ceci:
ALTER TABLE [dbo].[Questions] WITH CHECK ADD CONSTRAINT [FK_dbo.Questions_dbo.Categories_CategoryId] FOREIGN KEY([CategoryId]) REFERENCES [dbo].[Categories] ([Id]) ON DELETE CASCADE GO
et exécuté 'add-migration AnswerCascadeDelete` et il m'a dit qu'il n'y avait pas changements ....
Est-ce que quelqu'un sait pourquoi?
En guise de mise à jour, voici mon DbContext
modelBuilder.Entity<Category>().HasMany(m => m.Questions).WithOptional().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true);
Comme vous pouvez le voir, j'ai explicitement défini WillCascadeOnDelete
sur toutes les relations.
Je pensais que la plupart seraient définis par défaut, et dans ce cas, cela ne génère en fait aucun code dans la migration.
Mais lorsque je vérifie l'une de mes tables, seules certaines d'entre elles ont activé la suppression en cascade et je ne comprends pas pourquoi ....
3 Réponses :
Pour autant que je sache, EF traite les relations et la suppression en cascade via les paramètres de configuration suivants:
Ne pas de suppression en cascade si:
.WillCascadeOnDelete(false)
.WithOptional()
Effectuer une suppression en cascade si:
.WillCascadeOnDelete(true)
.WithRequired(/*subject*/)
Remarque: ceux-ci peuvent également être déclenchés par des annotations de données, par exemple; [RequiredAttribute]
, ou, la variante facultative; en utilisant Nullable
Maintenant, dans votre contrainte il y a:
ALTER TABLE [dbo]. [Answers] WITH CHECK ADD CONSTRAINT [FK_dbo.Answers_dbo.Questions_QuestionId] FOREIGN KEY ([QuestionId]) RÉFÉRENCES [dbo]. [Questions] ([Id]) ALLER
Mais cela renvoie aux réponses et non aux questions. Donc, je pense que la contrainte est valide:
Une question peut être sans réponse.
Je vais rassembler si vous vérifiez la contrainte sur les questions
, vous trouverez la suppression en cascade activée.
Je vois ce que vous dites, mais vous pourriez faire valoir le même point pour les questions sur les catégories. Une catégorie peut exister sans aucune question, mais elle applique toujours la suppression en cascade car une question ne peut pas exister sans catégorie. De même, une réponse ne peut pas exister sans question, elle doit donc suivre les mêmes règles, mais ce n'est pas le cas.
C'est peut-être la documentation qui est trompeuse ou tout simplement erronée. La documentation officielle < / a> vous dit ceci:
Vous pouvez configurer la suppression en cascade sur une relation en utilisant la méthode WillCascadeOnDelete. Si une clé étrangère sur l'entité dépendante n'est pas nullable, alors Code First définit la suppression en cascade sur la relation. Si une clé étrangère sur l'entité dépendante est nullable, Code First ne définit pas la suppression en cascade sur la relation, et lorsque le principal est supprimé, la clé étrangère sera définie sur null.
Donc, cela dit en gros que le comportement par défaut dépend de la possibilité de nullité de votre clé étrangère et n'est pas d'activer la suppression en cascade sur toutes les relations par défaut comme indiqué dans le lien que vous avez fourni.
Je vois exactement la même chose dans votre cas:
CategoryId
est nullable, ce qui empêche l'utilisation de la suppression en cascade par défaut, vous devez donc l'activer explicitement QuestionId
n'est pas nullable, ce qui entraîne l'utilisation de la suppression en cascade par défaut mais vous pouvez la désactiver explicitement (ce que vous n'avez pas essayé, pour autant que je sache, vous avez seulement essayé de l'activer, mais il était déjà activé par défaut) Quant à savoir pourquoi il n'y a pas de suppression en cascade explicite dans l'autre cas, je ne suis pas sûr, mais je pense que cela pourrait également être par défaut dans SQL, donc WillCascadeOnDelete (true)
ne le fait tout simplement pas changer quoi que ce soit de n'importe quel côté. Cependant, vous pourriez obtenir des résultats différents si vous essayez WillCascadeOnDelete (false)
qui devrait remplacer le comportement par défaut basé sur la documentation.
Je suppose que vous voulez dire que CriteriaId
est nullable? Parce que QuestionId
ne l'est pas. J'ai configuré le CriteriaId
pour forcer la suppression en cascade, ce qui est très bien. Mais comme Answers, Attributes ne semble pas avoir la suppression en cascade activée même lorsque vous définissez WillCascadeOnDelete
sur true. De plus, AttributeId / AnswerId est obligatoire, donc la suppression en cascade doit être activée, mais ce n'est pas le cas. J'ai mis à jour ma question pour afficher mon DbContext dans son intégralité
@ r3plica désolé, je voulais dire CategoryId
puisque le premier exemple concerne la relation Question
-to- Category
. J'ai modifié ma réponse en conséquence.
Coolio, ça tient toujours. Criteria a la suppression en cascade qui semble avoir été extraite de WillCascadeOnDelete
. Je n'arrive toujours pas à comprendre pourquoi les autres ne le sont pas ...
@ r3plica ce que je voulais dire, c'est que cela pourrait être le comportement par défaut pour EntityFramework et SQL Server, donc il n'ajoute pas l'instruction explicite. Cependant, je ne suis pas sûr de cela, des expériences seraient nécessaires. Avez-vous essayé WillCascadeOnDelete (false)
juste pour voir si cela change le comportement par défaut possible?
Cela ne semble pas être le comportement par défaut, mais j'ai trouvé une solution
Donc, cela me dérangeait; J'ai décidé de modifier mon DbContext . J'ai d'abord désactivé toutes les suppressions en cascade, puis j'ai mis à jour la base de données comme ceci:
AddForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers", "Id", cascadeDelete: true);
Lorsque cela s'est exécuté, il a mis à jour correctement les clés étrangères. Je pouvais voir ceci:
public partial class EnableCascadeDelete : DbMigration { public override void Up() { DropForeignKey("dbo.ImageText", "ImageId", "dbo.Images"); DropForeignKey("dbo.Images", "AnswerId", "dbo.Answers"); DropForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers"); DropForeignKey("dbo.Answers", "QuestionId", "dbo.Questions"); DropForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria"); DropForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes"); DropForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Questions", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Charges", "UserId", "dbo.Users"); DropForeignKey("dbo.Searches", "UserId", "dbo.Users"); DropIndex("dbo.Images", new[] { "AnswerId" }); DropIndex("dbo.ImageText", new[] { "ImageId" }); AddForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers", "Id", cascadeDelete: true); AddForeignKey("dbo.Answers", "QuestionId", "dbo.Questions", "Id", cascadeDelete: true); AddForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria", "Id", cascadeDelete: true); AddForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes", "Id", cascadeDelete: true); AddForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Questions", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations", "Id", cascadeDelete: true); AddForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations", "Id", cascadeDelete: true); AddForeignKey("dbo.Charges", "UserId", "dbo.Users", "Id", cascadeDelete: true); AddForeignKey("dbo.Searches", "UserId", "dbo.Users", "Id", cascadeDelete: true); DropTable("dbo.ImageText"); DropTable("dbo.Images"); } public override void Down() { CreateTable( "dbo.ImageText", c => new { Id = c.Int(nullable: false, identity: true), ImageId = c.Int(nullable: false), Text = c.String(), Delay = c.Int(nullable: false), }) .PrimaryKey(t => t.Id); CreateTable( "dbo.Images", c => new { Id = c.Int(nullable: false, identity: true), AnswerId = c.Int(nullable: false), Url = c.String(), }) .PrimaryKey(t => t.Id); DropForeignKey("dbo.Searches", "UserId", "dbo.Users"); DropForeignKey("dbo.Charges", "UserId", "dbo.Users"); DropForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Questions", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes"); DropForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria"); DropForeignKey("dbo.Answers", "QuestionId", "dbo.Questions"); DropForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers"); CreateIndex("dbo.ImageText", "ImageId"); CreateIndex("dbo.Images", "AnswerId"); AddForeignKey("dbo.Searches", "UserId", "dbo.Users", "Id"); AddForeignKey("dbo.Charges", "UserId", "dbo.Users", "Id"); AddForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations", "Id"); AddForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations", "Id"); AddForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Questions", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes", "Id"); AddForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria", "Id"); AddForeignKey("dbo.Answers", "QuestionId", "dbo.Questions", "Id"); AddForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers", "Id"); AddForeignKey("dbo.Images", "AnswerId", "dbo.Answers", "Id"); AddForeignKey("dbo.ImageText", "ImageId", "dbo.Images", "Id"); } }
Ce que je pouvais voir était correct. Ensuite, j'ai créé une nouvelle migration après avoir modifié mon DbContext retour:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Table renames modelBuilder.Entity<Criteria>().ToTable("Criteria"); modelBuilder.Entity<IdentityRole>().ToTable("Roles"); modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles"); modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims"); modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins"); // One to One modelBuilder.Entity<Attribute>().HasOptional(m => m.Type).WithRequired(m => m.Attribute).WillCascadeOnDelete(false); modelBuilder.Entity<Attribute>().HasOptional(m => m.Operation).WithRequired(m => m.Attribute).WillCascadeOnDelete(false); modelBuilder.Entity<Answer>().HasOptional(m => m.Scenario).WithRequired(m => m.Answer).WillCascadeOnDelete(false); modelBuilder.Entity<Answer>().HasOptional(m => m.Criteria).WithMany().HasForeignKey(m => m.CriteriaId).WillCascadeOnDelete(false); // One to Many modelBuilder.Entity<Criteria>().HasMany(m => m.Attributes).WithRequired().HasForeignKey(m => m.CriteriaId).WillCascadeOnDelete(true); modelBuilder.Entity<IdentityRole>().HasMany(m => m.Users).WithRequired().HasForeignKey(m => m.RoleId).WillCascadeOnDelete(false); modelBuilder.Entity<Organisation>().HasMany(m => m.Feeds).WithRequired().HasForeignKey(m => m.OrganisationId).WillCascadeOnDelete(true); modelBuilder.Entity<Organisation>().HasMany(m => m.Users).WithRequired().HasForeignKey(m => m.OrganisationId).WillCascadeOnDelete(true); modelBuilder.Entity<Question>().HasMany(m => m.Answers).WithRequired(m => m.Question).HasForeignKey(m => m.QuestionId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Sortations).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Criteria).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Feeds).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Questions).WithOptional().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<Category>().HasMany(m => m.Quotes).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true); modelBuilder.Entity<User>().HasMany(m => m.Searches).WithRequired().HasForeignKey(m => m.UserId).WillCascadeOnDelete(true); modelBuilder.Entity<User>().HasMany(m => m.Charges).WithRequired().HasForeignKey(m => m.UserId).WillCascadeOnDelete(true); modelBuilder.Entity<Attribute>().HasMany(m => m.Formulas).WithRequired().HasForeignKey(m => m.AttributeId).WillCascadeOnDelete(true); modelBuilder.Entity<Answer>().HasMany(m => m.Formulas).WithRequired().HasForeignKey(m => m.AnswerId).WillCascadeOnDelete(true); // Create our primary keys modelBuilder.Entity<IdentityUserLogin>().HasKey(m => m.UserId); modelBuilder.Entity<IdentityRole>().HasKey(m => m.Id); modelBuilder.Entity<IdentityUserRole>().HasKey(m => new {m.RoleId, m.UserId}); modelBuilder.Entity<AttributeOperation>().HasKey(m => m.AttributeId); modelBuilder.Entity<AttributeType>().HasKey(m => m.AttributeId); modelBuilder.Entity<Scenario>().HasKey(m => m.AnswerId); }
Ce qui a généré ceci:
public partial class DisableCascadeDelete : DbMigration { public override void Up() { DropForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers"); DropForeignKey("dbo.Images", "AnswerId", "dbo.Answers"); DropForeignKey("dbo.Answers", "QuestionId", "dbo.Questions"); DropForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria"); DropForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes"); DropForeignKey("dbo.ImageText", "ImageId", "dbo.Images"); DropForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Questions", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Charges", "UserId", "dbo.Users"); DropForeignKey("dbo.Searches", "UserId", "dbo.Users"); AddForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers", "Id"); AddForeignKey("dbo.Images", "AnswerId", "dbo.Answers", "Id"); AddForeignKey("dbo.Answers", "QuestionId", "dbo.Questions", "Id"); AddForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria", "Id"); AddForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes", "Id"); AddForeignKey("dbo.ImageText", "ImageId", "dbo.Images", "Id"); AddForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Questions", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories", "Id"); AddForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations", "Id"); AddForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations", "Id"); AddForeignKey("dbo.Charges", "UserId", "dbo.Users", "Id"); AddForeignKey("dbo.Searches", "UserId", "dbo.Users", "Id"); } public override void Down() { DropForeignKey("dbo.Searches", "UserId", "dbo.Users"); DropForeignKey("dbo.Charges", "UserId", "dbo.Users"); DropForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations"); DropForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Questions", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories"); DropForeignKey("dbo.ImageText", "ImageId", "dbo.Images"); DropForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes"); DropForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria"); DropForeignKey("dbo.Answers", "QuestionId", "dbo.Questions"); DropForeignKey("dbo.Images", "AnswerId", "dbo.Answers"); DropForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers"); AddForeignKey("dbo.Searches", "UserId", "dbo.Users", "Id", cascadeDelete: true); AddForeignKey("dbo.Charges", "UserId", "dbo.Users", "Id", cascadeDelete: true); AddForeignKey("dbo.Users", "OrganisationId", "dbo.Organisations", "Id", cascadeDelete: true); AddForeignKey("dbo.Feeds", "OrganisationId", "dbo.Organisations", "Id", cascadeDelete: true); AddForeignKey("dbo.Sortations", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Quotes", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Questions", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Feeds", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.Criteria", "CategoryId", "dbo.Categories", "Id", cascadeDelete: true); AddForeignKey("dbo.ImageText", "ImageId", "dbo.Images", "Id", cascadeDelete: true); AddForeignKey("dbo.AttributeFormulas", "AttributeId", "dbo.Attributes", "Id", cascadeDelete: true); AddForeignKey("dbo.Attributes", "CriteriaId", "dbo.Criteria", "Id", cascadeDelete: true); AddForeignKey("dbo.Answers", "QuestionId", "dbo.Questions", "Id", cascadeDelete: true); AddForeignKey("dbo.Images", "AnswerId", "dbo.Answers", "Id", cascadeDelete: true); AddForeignKey("dbo.AnswerFormulas", "AnswerId", "dbo.Answers", "Id", cascadeDelete: true); } }
Comme vous pouvez le voir, chaque clé étrangère a maintenant:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Table renames modelBuilder.Entity<Criteria>().ToTable("Criteria"); modelBuilder.Entity<IdentityRole>().ToTable("Roles"); modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles"); modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims"); modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins"); // One to One modelBuilder.Entity<Attribute>().HasOptional(m => m.Type).WithRequired(m => m.Attribute).WillCascadeOnDelete(false); modelBuilder.Entity<Attribute>().HasOptional(m => m.Operation).WithRequired(m => m.Attribute).WillCascadeOnDelete(false); modelBuilder.Entity<Answer>().HasOptional(m => m.Scenario).WithRequired(m => m.Answer).WillCascadeOnDelete(false); modelBuilder.Entity<Answer>().HasOptional(m => m.Criteria).WithMany().HasForeignKey(m => m.CriteriaId).WillCascadeOnDelete(false); // One to Many modelBuilder.Entity<Criteria>().HasMany(m => m.Attributes).WithRequired().HasForeignKey(m => m.CriteriaId).WillCascadeOnDelete(false); modelBuilder.Entity<IdentityRole>().HasMany(m => m.Users).WithRequired().HasForeignKey(m => m.RoleId).WillCascadeOnDelete(false); modelBuilder.Entity<Organisation>().HasMany(m => m.Feeds).WithRequired().HasForeignKey(m => m.OrganisationId).WillCascadeOnDelete(false); modelBuilder.Entity<Organisation>().HasMany(m => m.Users).WithRequired().HasForeignKey(m => m.OrganisationId).WillCascadeOnDelete(false); modelBuilder.Entity<Question>().HasMany(m => m.Answers).WithRequired(m => m.Question).HasForeignKey(m => m.QuestionId).WillCascadeOnDelete(false); modelBuilder.Entity<Category>().HasMany(m => m.Sortations).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(false); modelBuilder.Entity<Category>().HasMany(m => m.Criteria).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(false); modelBuilder.Entity<Category>().HasMany(m => m.Feeds).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(false); modelBuilder.Entity<Category>().HasMany(m => m.Questions).WithOptional().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(false); modelBuilder.Entity<Category>().HasMany(m => m.Quotes).WithRequired().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(false); modelBuilder.Entity<User>().HasMany(m => m.Searches).WithRequired().HasForeignKey(m => m.UserId).WillCascadeOnDelete(false); modelBuilder.Entity<User>().HasMany(m => m.Charges).WithRequired().HasForeignKey(m => m.UserId).WillCascadeOnDelete(false); modelBuilder.Entity<Attribute>().HasMany(m => m.Formulas).WithRequired().HasForeignKey(m => m.AttributeId).WillCascadeOnDelete(false); modelBuilder.Entity<Answer>().HasMany(m => m.Formulas).WithRequired().HasForeignKey(m => m.AnswerId).WillCascadeOnDelete(false); // Create our primary keys modelBuilder.Entity<IdentityUserLogin>().HasKey(m => m.UserId); modelBuilder.Entity<IdentityRole>().HasKey(m => m.Id); modelBuilder.Entity<IdentityUserRole>().HasKey(m => new {m.RoleId, m.UserId}); modelBuilder.Entity<AttributeOperation>().HasKey(m => m.AttributeId); modelBuilder.Entity<AttributeType>().HasKey(m => m.AttributeId); modelBuilder.Entity<Scenario>().HasKey(m => m.AnswerId); }
Il s'agit donc explicitement de paramétrer l'option cascadeDelete
qui n'a jamais été présente.
Alors, que dois-je conclure? Il semble que lors de la configuration initiale d'un code de base de données, vous ne pouvez pas et ne devez pas compter sur EntityFramework pour créer une suppression en cascade. Si vous le souhaitez, vous devez le spécifier lors de la création. Cela devrait éviter que mon problème ne vous arrive. Mais, si c'est le cas, désactivez-le et réactivez-le lors de la prochaine migration et cela résoudra votre problème.