实体框架级联删除继承的类 [英] Entity Framework Cascade Delete For Inherited class

查看:85
本文介绍了实体框架级联删除继承的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

在我的情况下,我有一个基类(数据库中有它自己的表) )

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.

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");

下面是 IntProperties数据库表的快照。

Below is a snapshot of the database table for "IntProperties".

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

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.

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

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?

这不是一个重复的问题:因为就我而言,它是抽象基类的派生类。有人提到现有数据库是不可能的,但是幸运的是我没有现有数据库。我正在尝试通过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. Any help is very welcome!

推荐答案

对此已进行了多次报道和讨论,例如:实体框架中的级联删除(每个类型继承的表)。我会将其标记为重复,但是由于问题和Slauma的答案都是关于EF版本4,我认为是时候进行更新了。

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.

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

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.

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

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.

现在,如果您愿意...

Now if you do ...

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

...,您会看到EF only 发出一个 Delete 语句,用于 Master 。它依靠数据库将删除级联到 Properties 表。可以,但是 IntProperty TextProperty 的FK被违反了,因为它们确实 not 级联删除。

... you'll see that EF only emits one DELETE statement for Master. It relies on the database to cascade the delete to the Properties table. Well, it does, but then the FKs from IntProperty and TextProperty are violated, because these do not cascade deletes.

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

You can fix this by doing:

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

现在,EF显式删除属性和子类型。 1

Now EF explicitly deletes the properies and the subtypes.1

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

The funny thing is that EF knows perfectly well that for deleting a property, either by ...

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语句。

... it should emit two delete statements.

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

So that leaves you without tooling to configure the TPT association as cascaded. 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. This can incur a serious performance hit. But it will enable you to delete a master record (owning properties) by one delete statement.

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

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.

这篇关于实体框架级联删除继承的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆