显然,使用实体框架进行级联删除非常令人困惑。我发现了很多问题,但没有找到解决问题的方法。如果我手动将“删除规则”设置为级联,则所有工作正常。但是,通过Fluent API,我还没有找到在数据库中设置此属性的方法。

就我而言,我有一个基类(数据库中有它自己的表)

public abstract class PropertyBase
{
    public int PropertyID { get; set; }
    public string Name { get; set; }
    public virtual AspectBase AspectBase { get; set; }
}


我有派生类,这些类存储在每个类型的表中。

public class TextProperty : PropertyBase
{
    public string Value { get; set; }
}

public class IntProperty : PropertyBase
{
    public int Value { get; set; }
}


在我的数据库上下文中,我具有以下内容:

        modelBuilder.Entity<PropertyBase>()
            .ToTable("Properties")
            .HasKey(p => p.PropertyID);

        modelBuilder.Entity<IntProperty>()
            .ToTable("IntProperties");

        modelBuilder.Entity<TextProperty>()
            .ToTable("TextProperties");


下面是“ IntProperties”数据库表的快照。
c# -  Entity Framework 级联删除继承的类-LMLPHP

我需要在上图中设置所选外键的删除规则。如果我在数据库中手动执行此操作,则一切正常。我真的不知道如何实现这一目标。请帮忙。

我知道它必须与WillCascadeOnDelete有关,但是要能够通过Fluent API做到这一点,我可能需要一些导航属性?

这不是一个重复的问题:因为就我而言,它是抽象基类的派生类。有人提到现有数据库是不可能的,但是幸运的是我没有现有数据库。我正在尝试通过Fluent API完成此代码。任何帮助都非常欢迎!

最佳答案

已经对此进行了更频繁的报道和讨论,例如:Cascade delete in entity framework ( table per type inheritance )。我将其标记为重复,但是由于问题和Slauma的答案都是关于EF版本4,我认为是时候进行更新了。

令人沮丧的是,该错误(我认为是)仍然存在。我可能会忽略一些边缘情况(我可能会这样做),但是我认为在TPT中,基本类型和子类型之间的关系可能默认为级联删除。

如所提到的问题所示的错误仍然发生。对于您而言,如果您删除拥有属性集合的主实体,则会看到它。假设您有这个课程:

class Master
{
    public int ID { get; set; }
    public virtual ICollection<PropertyBase> Properties { get; set; }
}


并且关联Properties被标记为级联删除。

现在,如果您愿意...

var master = context.Find(x);
context.Masters.Remove(master);
context.SaveChanges();


...您会看到EF仅为DELETE发出一个Master语句。它依靠数据库将删除级联到Properties表。可以,但是IntPropertyTextProperty中的FK被违反了,因为它们不会级联删除。

您可以通过以下方法解决此问题:

var master = context.Include(m => m.Properties).Single(m => m.ID == x);
context.Masters.Remove(master);
context.SaveChanges();


现在,EF明确删除了属性和子类型。1

有趣的是,EF非常清楚删除属性的方法,可以通过...

var intProp = context.Properties.OfType<IntProp>().First();
context.Properties.Remove(intProp); // delete from the base table


... 要么 ...

var intProp = context.Properties.OfType<IntProp>().First();
context.IntProperties.Remove(intProp); // delete from the derived table


...它应该发出两个delete语句。

这样一来,您无需使用任何工具即可将TPT关联配置为级联。您必须将其手动添加到迁移脚本中。但是,这不会阻止EF对要删除的每个单个属性执行2条delete语句,因为它不知道数据库中的级联。这会导致严重的性能下降。但是,它将使您能够通过一条delete语句删除主记录(拥有属性)。



1与EF 4相比,这似乎是一种改进,在EF 4中,显然也必须为每个子记录都具有Remove语句。

10-05 21:09
查看更多