entity framework6:代码优先级联删除
所以这里有几个类似的问题,但我仍然有问题确定我在简化场景中缺少的是什么。
假设我有以下表格,巧妙地以自己的名字命名:
'JohnsParentTable' (Id, Description) 'JohnsChildTable' (Id, JohnsParentTableId, Description)
结果类看起来像这样
public class JohnsParentTable { public int Id { get; set; } public string Description { get; set; } public virtual ICollection JohnsChildTable { get; set; } public JohnsParentTable() { JohnsChildTable = new List(); } } internal class JohnsParentTableConfiguration : EntityTypeConfiguration { public JohnsParentTableConfiguration() { ToTable("dbo.JohnsParentTable"); HasKey(x => x.Id); Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); } } public class JohnsChildTable { public int Id { get; set; } public string Description { get; set; } public int JohnsParentTableId { get; set; } public JohnsParentTable JohnsParentTable { get; set; } } internal class JohnsChildTableConfiguration : EntityTypeConfiguration { public JohnsChildTableConfiguration() { ToTable("dbo.JohnsChildTable"); HasKey(x => x.Id); Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); HasRequired(a => a.JohnsParentTable).WithMany(c => c.JohnsChildTable).HasForeignKey(a => a.JohnsParentTableId); } }
在数据库中,我在父表中有一行,Id为1,子表中有两行绑定到该父表。 如果我这样做:
var parent = db.JohnsParentTable.FirstOrDefault(a => a.Id == 1)
正确填充对象。 但是,如果我尝试删除此行:
var parent = new Data.Models.JohnsParentTable() { Id = 1 }; db.JohnsParentTable.Attach(parent); db.JohnsParentTable.Remove(parent); db.SaveChanges();
entity framework尝试执行以下操作:
DELETE [dbo].[JohnsParentTable] WHERE ([Id] = @0) -- @0: '1' (Type = Int32) -- Executing at 1/23/2014 10:34:01 AM -06:00 -- Failed in 103 ms with error: The DELETE statement conflicted with the REFERENCE constraint "FK_JohnsChildTable_JohnsParentTable". The conflict occurred in database "mydatabase", table "dbo.JohnsChildTable", column 'JohnsParentTableId'. The statement has been terminated.
那么我的问题是我错过了什么以确保entity framework知道它必须在删除父项之前删除’JohnsChildTable’行?
这取决于您是希望entity framework删除子项,还是希望数据库处理它。
如果希望EF为所有子项生成delete语句并在删除父项之前执行这些语句,则必须先将所有子项加载到内存中。
所以你不能简单地只用填充的密钥创建一个“虚拟”实体,并期望删除子项。
为此,您必须让数据库处理删除。
子表上的外键必须启用级联删除。 如果是这种情况,Entity Framework只为父级创建一个delete语句,数据库也知道删除子级。
如果需要关系,entity framework会创建一个默认启用级联删除的外键,就像您的情况一样。 (外键不能为空)。
如果您自己创建了数据库,则必须记住启用它。
我认为最好覆盖OnModelCreating方法并添加此代码。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasRequired(t=>t.JohnsParentTable) .WithMany(t=>t.JohnsChildTables) .HasForeignKey(d=>d.JohnsParentTableId) .WillCascadeOnDelete(true); base.OnModelCreating(modelBuilder); }
我设置为true WillCascadeOnDelete(true)
在Visual Studio中打开模型文件。 右键单击Parent-Child关系,然后选择Properties。
在End1 OnDelete属性上,该值可能为None。 另一种选择是Cascade; 把它设置为那个。 现在删除父级会将删除级联到其子级。
干杯 –