如何使用fluent api为基表指定级联删除
本文关键字:级联 删除 基表 何使用 fluent api | 更新日期: 2023-09-27 18:10:10
问题:我如何让EF 4.1使用流利的api为基表指定外键约束上的ON DELETE CASCADE
选项?我知道如何处理与其他表的关系,但是如何让它为TPT(每类型表)表生成这种关系呢?
描述:让我指出,我指的不是外键关系。对于DbContext,我总是为实体使用Mapping对象,这只是因为在大多数情况下,我更喜欢显式的方式,而不是接受约定的方式。也就是说,TPT表的所有配置都在EntityTypeConfiguration<SomeEntityClass>
类中处理。
当我通过创建从另一个类派生的新类来定义TPT关系时,ON DELETE CASCADE
不会在SQL约束中生成,这就是问题所在。
看一下下面的代码…
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
}
public class OtherPerson : Person
{
public string SomeOtherProperty { get; set; }
}
public class PersonMap : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Person>
{
public PersonMap()
{
this.HasKey(t => t.PersonId); // Primary Key
this.Property(t => t.PersonId)
.HasColumnName("PersonId") // Explicitly set column name
.IsRequired() // Field is required / NOT NULL
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // Specify as Identity (Not necessary, but I'm explicit)
this.Property(t => t.Name)
.HasColumnName("Name") // Explicitly set column name
.IsRequired() // Field is required / NOT NULL
.HasMaxLength(50); // Max Length
this.ToTable("People"); // Map to table name People
}
}
public class OtherPersonMap : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<OtherPerson>
{
public OtherPersonMap()
{
this.Property(t => t.SomeOtherProperty)
.HasColumnName("SomeOtherProperty") // Explicitly set column name
.IsRequired() // Field is required / NOT NULL
.HasMaxLength(10); // Max Length
this.ToTable("OtherPeople"); /* Map to table name OtherPeople
* This also causes TPT to create a shared primary key from the base table
* and double serving as a foreign key to base table.
*/
}
上面的代码非常简单。我有2种类型,他们在数据库中正确创建。如果我创建一个新的OtherPerson
并保存到数据库,它会正确地创建2条记录,首先是People
表中的一条记录,另一条是OtherPeople
表中的一条记录,具有共享主键,也是从OtherPeople到People的外键。现在,如果我在代码中删除OtherPerson, DbContext或EF就会正确地删除这两条记录。但是,如果我直接从数据库中删除该记录,则会在People
表中留下一条孤儿记录。
那么,我如何得到ON DELETE CASCADE
被指定为使用流利的api生成的基表的外键约束?
对不起,这个问题太长了,但我只是想尽可能地描述我的问题。
现在,DbContext(更确切地说是EF)正确地删除了这两个记录,如果I删除我的代码中的OtherPerson。但是,我是否应该删除记录直接从数据库中取出,孤儿记录则留在数据库中
你似乎说你想从OtherPeople
表(派生实体)中删除一条记录,级联删除应该确保People
表(基本实体)中相应的记录也将被删除。
但这是错误的方向。EF创建了一个从基本实体表到派生实体表的关系和外键约束,因此:PK表为People
, FK表为OtherPeople
。在此关系上使用级联删除,您只能确保在相应的People
记录被删除时删除OtherPeople
记录,而不是相反。
这个关系本身——也没有级联删除——确保你不能在OtherPeople
表中获得孤儿记录,因为它会违反FK约束。(删除Person
时不能删除相应的OtherPerson
)
对于您的特殊目的,您实际上需要在数据库中添加第二个FK约束,其中PK表为OtherPeople
, FK
表为People
。这种关系根本不是由EF TPT映射创建的,它也只会在People
上的PK不是一个身份(至少在SQL Server中)时才会起作用。但它是你模型中的一个身份。所以你甚至不能在数据库中使用级联删除来创建这种关系,更不用说EF了。
回到EF实际上在数据库中创建的关系(这不是您想要的级联删除),我认为EF Code-First中没有映射选项,这将允许您控制TPT映射所需的关系。唯一的方法是直接在数据库中完成,或者——如果你想从代码优先模型生成数据库——在自定义初始化器中编写原始SQL语句(设置级联删除),并在创建所有表和关系后将其发送给数据库。
在数据库中,People
和Order
很像,OtherPeople
和OrderItem
很像,只是不是1-to-*
,而是1-to-0..1
的关系。您想要的是,如果子OrderItem
被删除,则父Order
被删除,这意味着依赖将删除主体。