Entity Framework 继承的级联删除 class
Entity Framework Cascade Delete For Inherited class
显然,使用 Entity Framework 进行级联删除非常令人困惑。我发现了很多问题,但我还没有找到解决问题的方法。如果我手动设置 "Delete Rule" 级联它一切正常。但是通过 Fluent API 我还没有找到在数据库中设置这个 属性 的方法。
在我的例子中,我有一个基础 class(在数据库中有自己的 table)
public abstract class PropertyBase
{
public int PropertyID { get; set; }
public string Name { get; set; }
public virtual AspectBase AspectBase { get; set; }
}
并且我导出了 classes,每个类型存储 Table。
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" 的数据库 table 的快照。
我需要设置上图中选中的外键的删除规则。如果我在数据库中手动执行此操作,则一切正常。我真的不知道如何实现这一目标。请帮忙。
我知道它必须与 WillCascadeOnDelete 相关,但为了能够使用 Fluent API 执行此操作,我可能需要一些导航属性?
这不是一个重复的问题:因为在我的例子中,它是抽象基础 class 的派生 class。有人提到使用现有数据库是不可能的,但幸运的是我没有现有数据库。我正在尝试使用 Fluent API 优先完成此代码。非常欢迎任何帮助!
级联删除只能发生在数据库级别,EF在这方面不会什么都不做。这里的问题是您(和许多其他人 :P)混淆了 WillCascadeOnDelete 的用法。它仅在您使用 Code First 开发流程时有用,在这种情况下 EF 将生成迁移代码以在数据库外键中设置此 属性 仅此而已,由数据库删除关系。
当您使用数据库优先工作流时,就像您的情况一样,此设置将被忽略。
这已被更频繁地报道和讨论,例如此处:Cascade delete in entity framework ( table per type inheritance )。我会将其标记为重复,但由于问题和 Slauma 的回答是关于 EF 版本 4,我认为是时候进行更新了。
令人沮丧的是错误(我认为是)仍然存在。我可能会忽略一些边缘情况(我可能会这样做),但我认为在 TPT 中,基本类型和子类型之间的关系可能默认为级联删除。
所提到的问题中指出的错误仍然出现。在您的情况下,如果您删除拥有属性集合的主实体,您会看到它。假设你有这个 class:
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 仅 为 Master
发出一个 DELETE
语句。它依靠数据库将删除级联到 Properties
table。好吧,确实如此,但是来自 IntProperty
和 TextProperty
的 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
语句。
显然,使用 Entity Framework 进行级联删除非常令人困惑。我发现了很多问题,但我还没有找到解决问题的方法。如果我手动设置 "Delete Rule" 级联它一切正常。但是通过 Fluent API 我还没有找到在数据库中设置这个 属性 的方法。
在我的例子中,我有一个基础 class(在数据库中有自己的 table)
public abstract class PropertyBase
{
public int PropertyID { get; set; }
public string Name { get; set; }
public virtual AspectBase AspectBase { get; set; }
}
并且我导出了 classes,每个类型存储 Table。
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" 的数据库 table 的快照。
我需要设置上图中选中的外键的删除规则。如果我在数据库中手动执行此操作,则一切正常。我真的不知道如何实现这一目标。请帮忙。
我知道它必须与 WillCascadeOnDelete 相关,但为了能够使用 Fluent API 执行此操作,我可能需要一些导航属性?
这不是一个重复的问题:因为在我的例子中,它是抽象基础 class 的派生 class。有人提到使用现有数据库是不可能的,但幸运的是我没有现有数据库。我正在尝试使用 Fluent API 优先完成此代码。非常欢迎任何帮助!
级联删除只能发生在数据库级别,EF在这方面不会什么都不做。这里的问题是您(和许多其他人 :P)混淆了 WillCascadeOnDelete 的用法。它仅在您使用 Code First 开发流程时有用,在这种情况下 EF 将生成迁移代码以在数据库外键中设置此 属性 仅此而已,由数据库删除关系。
当您使用数据库优先工作流时,就像您的情况一样,此设置将被忽略。
这已被更频繁地报道和讨论,例如此处:Cascade delete in entity framework ( table per type inheritance )。我会将其标记为重复,但由于问题和 Slauma 的回答是关于 EF 版本 4,我认为是时候进行更新了。
令人沮丧的是错误(我认为是)仍然存在。我可能会忽略一些边缘情况(我可能会这样做),但我认为在 TPT 中,基本类型和子类型之间的关系可能默认为级联删除。
所提到的问题中指出的错误仍然出现。在您的情况下,如果您删除拥有属性集合的主实体,您会看到它。假设你有这个 class:
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 仅 为 Master
发出一个 DELETE
语句。它依靠数据库将删除级联到 Properties
table。好吧,确实如此,但是来自 IntProperty
和 TextProperty
的 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
语句。