如果我尝试删除“子”行,我总是会遇到异常。这是一个片段:
using (var context = new CompanyContext())
{
ItemType itemType = context.ItemTypes.FirstOrDefault(i => i.Name == "ServerType");
ItemTypeItem itemTypeItem = itemType.Items.FirstOrDefault(i => i.Name == "DatabaseServer");
itemType.Items.Remove(itemTypeItem);
context.SaveChanges(); <=== exception!
}
SaveChanges()
方法抛出以下异常。
“由于一个或多个外键属性不可为空,因此无法更改关系。当对关系进行更改时,相关的外键属性将设置为空值。 -key不支持空值,必须定义新关系,必须为foreign-key属性分配另一个非空值,或者必须删除不相关的对象。“
实体配置
public class ItemTypeConfiguration : NamedEntityConfiguration<ItemType>
{
public ConfigurationColumn ParentIDColumn;
public ConfigurationColumn ValidationPatternColumn;
public ItemTypeConfiguration() : base()
{
ParentIDColumn = new ConfigurationColumn() { Name = "ParentID", Ordinal = base.LastOrdinalPosition + 1 };
ValidationPatternColumn = new ConfigurationColumn() { Name = "ValidationPattern", Length = 1024, Ordinal=base.LastOrdinalPosition + 2};
this.Property(t => t.ParentID)
.HasColumnName(ParentIDColumn.Name)
.HasColumnOrder(ParentIDColumn.Ordinal);
this.HasOptional(t => t.Parent).WithMany().HasForeignKey(u => u.ParentID).WillCascadeOnDelete(false);
this.Property(t => t.ValidationPattern)
.HasColumnName(ValidationPatternColumn.Name)
.HasColumnOrder(ValidationPatternColumn.Ordinal)
.HasMaxLength(ValidationPatternColumn.Length);
}
...
public class ItemTypeItemConfiguration : NamedEntityConfiguration<ItemTypeItem>
{
public ConfigurationColumn ItemTypeIDColumn;
public ItemTypeItemConfiguration() : base()
{
ItemTypeIDColumn = new ConfigurationColumn(){Name="ItemTypeID", IsRequired=true, Ordinal= base.LastOrdinalPosition+1};
this.Property(t => t.ItemTypeID)
.HasColumnName(ItemTypeIDColumn.Name)
.HasColumnOrder(ItemTypeIDColumn.Ordinal);
this.HasRequired(t => t.ItemType).WithMany(t=>t.Items).HasForeignKey(u => u.ItemTypeID).WillCascadeOnDelete(true);
}
...
我找到了博客,但我没有“DeleteObject”方法。
有什么想法吗?谢谢。
答案 0 :(得分:48)
您需要删除ItemTypeItem。 不可能只将它从Items列表中删除,因为它本身不存在,因为它有一个不可为空的外键引用ItemType(ItemTypeID)。
删除ItemTypeItem add
context.Entry(itemTypeItem).State = EntityState.Deleted;
答案 1 :(得分:44)
在实体框架6.0中,如果从主要上下文集中删除实体,它将起作用。例如,要删除投资实体,您将执行以下操作:
context.Investments.Remove(entity);
context.SaveChanges();
这与尝试从其父/所有者中删除实体不同,如下所示:
bankAccount.Investments.Remove(entity);
context.SaveChanges();
这将抛出上面列出的无法更改的关系。希望这会有所帮助。
答案 2 :(得分:19)
在实体6.0中,存在以下区别:
context.Investments.Remove(entity);
和
context.Entry(entity).State = EntityState.Deleted;
当启用第一个和级联删除时,EF将在内部执行必要的子集合删除。 使用第二个选项时,EF不会处理必要的删除,但让您处理这些子对象的重新绑定/删除。
答案 3 :(得分:1)
出现此问题是因为我们尝试删除父表仍存在子表数据。我们在级联删除的帮助下解决了这个问题。
在dbcontext类的模型Create方法中。
modelBuilder.Entity<Job>()
.HasMany<JobSportsMapping>(C => C.JobSportsMappings)
.WithRequired(C => C.Job)
.HasForeignKey(C => C.JobId).WillCascadeOnDelete(true);
modelBuilder.Entity<Sport>()
.HasMany<JobSportsMapping>(C => C.JobSportsMappings)
.WithRequired(C => C.Sport)
.HasForeignKey(C => C.SportId).WillCascadeOnDelete(true);
之后,在我们的API调用中
var JobList = Context.Job
.Include(x => x.JobSportsMappings) .ToList();
Context.Job.RemoveRange(JobList);
Context.SaveChanges();
级联删除选项使用此简单代码删除父级以及父级相关子表。以这种简单的方式尝试。
删除用于删除数据库中记录列表的范围谢谢
答案 4 :(得分:0)
描述错误发生原因的其他答案是正确的,但是当在父对象的子对象集合上调用 .Remove
时,实际上可以让 EF 完全删除子对象,您不需要直接转到数据库上下文中的子实体表并从中删除它。
要让它发挥作用,您需要建立一个识别关系,as described in this answer。