【发布时间】:2019-01-07 10:36:21
【问题描述】:
我在 EntityFramework 6 中发现了一个小问题,我不确定是不是我做错了什么。
默认情况下,我认为应该按照此处所述启用它: http://www.entityframeworktutorial.net/code-first/cascade-delete-in-code-first.aspx
但我在我的应用程序中发现了一些情况并非如此。 我有这个模型:
public class Category
{
public string Id { get; set; }
[Required] [MaxLength(100)] [Index(IsUnique = true)] public string Name { get; set; }
[MaxLength(2083)] public string Image { get; set; }
public bool Live { get; set; }
public IList<Criteria> Criteria { get; set; }
public IList<Feed> Feeds { get; set; }
public IList<Sortation> Sortations { get; set; }
public IList<Quote> Quotes { get; set; }
public IList<Question> Questions { get; set; }
}
它没有用于问题的级联删除,因此我将我的 DbContext 更新为:
modelBuilder.Entity<Category>().HasMany(m => m.Questions).WithOptional().HasForeignKey(m => m.CategoryId).WillCascadeOnDelete(true);
当我运行update-database 时,我看到约束现在是正确的:
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
我尝试删除一个类别,但出现错误:
DELETE 语句与 REFERENCE 约束冲突
经过调查,它正在抱怨 Answers 表。以下是 Question 和 Answer 模型:
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; }
}
映射如下所示:
modelBuilder.Entity<Question>().HasMany(m => m.Answers).WithRequired(m => m.Question).HasForeignKey(m => m.QuestionId)
但如果我检查约束,我会看到:
ALTER TABLE [dbo].[Answers] WITH CHECK ADD CONSTRAINT [FK_dbo.Answers_dbo.Questions_QuestionId] FOREIGN KEY([QuestionId])
REFERENCES [dbo].[Questions] ([Id])
GO
我认为是错误的,我认为应该是:
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
所以我将映射更改为:
modelBuilder.Entity<Question>().HasMany(m => m.Answers).WithRequired(m => m.Question).HasForeignKey(m => m.QuestionId).WillCascadeOnDelete(true);
然后运行“add-migration AnswerCascadeDelete”,它告诉我没有任何变化......
有人知道为什么吗?
作为更新,这是我的 DbContext:
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);
}
}
如您所见,我已在所有关系上明确设置WillCascadeOnDelete。
我认为大多数都是默认设置的,在这种情况下,它实际上不会在迁移中生成任何代码。
但是当我检查我的任何表时,只有一些表启用了级联删除,我不明白为什么....
【问题讨论】:
标签: c# entity-framework