简体   繁体   English

实体框架级联删除继承类

[英]Entity Framework Cascade Delete For Inherited class

Apparently Cascade Deleting with Entity Framework is very confusing. 显然,使用实体框架进行级联删除非常令人困惑。 I found lot's of questions but I have not found a solution for my problem. 我发现了很多问题,但我找不到解决问题的方法。 If I manually set the "Delete Rule" to cascade it all works. 如果我手动设置“删除规则”以级联它都可以。 But via Fluent API I haven't found a way to set this property in the database. 但是通过Fluent API,我还没有找到在数据库中设置此属性的方法。

In my case I have a base class (with it's own table in the database) 在我的情况下,我有一个基类(在数据库中有自己的表)

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

And I have derived classes which are stored Table Per Type. 我已经派生了存储Table Per Type的类。

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

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

In my database context I have the following: 在我的数据库上下文中,我有以下内容:

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

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

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

Below is a snapshot of the database table for "IntProperties". 下面是“IntProperties”的数据库表的快照。 IntProperties的关键

I need to set the Delete rule of the selected foreignkey in the image above. 我需要在上图中设置所选外键的删除规则。 If I do this manually in the database, then it all works fine. 如果我在数据库中手动执行此操作,那么一切正常。 I really have no idea on how to achieve this. 我真的不知道如何实现这一目标。 Please help. 请帮忙。

I know it has to be something with WillCascadeOnDelete, but to be able to do this with Fluent API I probably need some navigation properties? 我知道它必须是WillCascadeOnDelete的东西,但是为了能够用Fluent API做这个我可能需要一些导航属性?

This is not a duplicate question: because in my case it's a derived class of the abstract base class. 这不是一个重复的问题:因为在我的情况下,它是抽象基类的派生类。 Some have mentioned that it is not possible with an existing database, but luckily I don't have an existing database. 有人提到现有的数据库是不可能的,但幸运的是我没有现有的数据库。 I am trying to accomplish this Code First and with Fluent API. 我正在尝试使用Fluent API完成此Code First。 Any help is very welcome! 非常欢迎任何帮助!

This has been reported and discussed more often, for example here: Cascade delete in entity framework ( table per type inheritance ) . 已经更频繁地报告和讨论了这个问题,例如: 实体框架中的级联删除(每类继承的表) I would mark this as a duplicate, but since the question and Slauma's answer are about EF version 4, I think it's time for an update. 我将此标记为重复,但由于问题和Slauma的答案是关于EF版本4,我认为是时候进行更新了。

The discouraging part is that the bug (which I think it is) still occurs. 令人沮丧的是,虫子(我认为它)仍然存在。 I may be overlooking some edge cases (I probably do), but I think in TPT the relation between base and subtype could default to cascaded delete. 我可能会忽略一些边缘情况(我可能会这样做),但我认为在TPT中,base和subtype之间的关系可以默认为级联删除。

The error as indicated in the referred question still occurs. 仍然会出现所提问题中指出的错误。 In your case you would see it if you'd delete a master entity that owns a collection of properties. 在您的情况下,如果您删除拥有属性集合的主实体,您将看到它。 Let's say you have this class: 假设你有这门课程:

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

And the association Properties is marked as cascaded delete. 并且关联Properties被标记为级联删除。

Now if you do ... 现在,如果你这样做......

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

... you'll see that EF only emits one DELETE statement for Master . ...你会看到EF Master发出一个DELETE语句。 It relies on the database to cascade the delete to the Properties table. 它依赖于数据库将删除级联到Properties表。 Well, it does, but then the FKs from IntProperty and TextProperty are violated, because these do not cascade deletes. 嗯,确实如此,但是后来IntPropertyTextProperty中的IntProperty被违反了,因为它们不会级联删除。

You can fix this by doing: 您可以通过以下方式解决此问题

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

Now EF explicitly deletes the properies and the subtypes. 现在EF明确删除了属性和子类型。 1 1

The funny thing is that EF knows perfectly well that for deleting a property, either by ... 有趣的是,EF非常清楚地知道删除房产要么......

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

... or ... ... 要么 ...

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

... it should emit two delete statements. ...它应该发出两个删除语句。

So that leaves you without tooling to configure the TPT association as cascaded. 因此,您无需工具即可将TPT关联配置为级联。 You'll have to add it to the migration scripts manually. 您必须手动将其添加到迁移脚本中。 However, that won't stop EF from executing 2 delete statements for each individual property that is to be deleted, because it's not aware of the cascade in the database. 但是,这不会阻止EF为要删除的每个单独属性执行2个删除语句,因为它不知道数据库中的级联。 This can incur a serious performance hit. 这可能会导致严重的性能损失。 But it will enable you to delete a master record (owning properties) by one delete statement. 但它将使您能够通过一个删除语句删除主记录(拥有属性)。


1 This seems to be an improvement compared to EF 4, where apparently it was necessary to have Remove statements for each child record too. 1与EF 4相比,这似乎是一种改进,显然每个子记录都必须有Remove语句。

Cascade deletions can only happens at database level, EF does not do nothing in this regards. 级联删除只能在数据库级别进行,EF在这方面不做任何事情。 The problem here is that you ( and many others :P) are confusing usage of WillCascadeOnDelete . 这里的问题是你(和许多其他人:P)混淆了WillCascadeOnDelete的使用。 It is useful only when you use Code First development flow, in this case EF will generate migration code to set this property in the database foreign key and nothing more, it is up to the database to delete relationships. 它仅在您使用Code First开发流程时才有用,在这种情况下,EF将生成迁移代码以在数据库外键中设置此属性,仅此而已由数据库删除关系。

When you work with database first workflow as it seems is your case, this setting is simply ignored. 当你使用数据库第一个工作流程时,就像你的情况一样,这个设置被简单地忽略了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM