【问题标题】:Entity Framework Cascade Delete For Inherited class继承类的实体框架级联删除
【发布时间】:2016-04-06 13:36:44
【问题描述】:

显然,使用实体框架进行级联删除非常令人困惑。我发现了很多问题,但我还没有找到解决我的问题的方法。如果我手动设置“删除规则”来级联它一切正常。但是通过 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”数据库表的快照。

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

我知道它必须与 WillCascadeOnDelete 相关,但为了能够使用 Fluent API 执行此操作,我可能需要一些导航属性?

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

【问题讨论】:

  • 您使用的是哪个版本的实体框架?

标签: c# entity-framework cascading-deletes


【解决方案1】:

这已被更频繁地报告和讨论,例如这里: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 onlyMaster 发出一个DELETE 语句。它依赖数据库将删除级联到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

...它应该发出两个删除语句。

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


1 与 EF 4 相比,这似乎是一个改进,显然在 EF 4 中,每个子记录也需要有 Remove 语句。

【讨论】:

  • 亲爱的格特·阿诺德。谢谢你有时间。这不是我想要的,但你的回答指出了我忽略的一个问题。我的 Master 类也是一个带有派生类的抽象基类。我的属性列表放在抽象主类中。我试图删除(移除)派生类,因此没有链接上下文中的属性。
  • 不客气 :) 我觉得很遗憾,使用 EF 很难顺利删除对象图。 NHibernate 从一开始就在这方面做得更好。也许 EF7 会显着改善这一点。
【解决方案2】:

级联删除只能发生在数据库级别,EF 在这方面没有做任何事情。这里的问题是您(和许多其他人:P)混淆了 WillCascadeOnDelete 的用法。它仅在您使用 Code First 开发流程时有用,在这种情况下,EF 将生成迁移代码以在数据库外键中设置此属性,仅此而已,由数据库删除关系。

当您使用似乎是您的情况的数据库优先工作流时,此设置将被忽略。

【讨论】:

  • 简短回答是否定的。那是因为您使用的是现有数据库。
  • 您是从带有迁移的模型生成数据库吗?
猜你喜欢
  • 2020-08-27
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多