简体   繁体   English

如何使用流利的api为基表指定Cascade Delete?

[英]How do you specify Cascade Delete for base tables using fluent api?

Question: How do I get EF 4.1 to specify the ON DELETE CASCADE option on the foreign key constraint using the fluent api for base tables? 问题:如何获得EF 4.1,使用基本表的流利api在外键约束上指定ON DELETE CASCADE选项? I know how to do it with relationships to other tables, but how do I have it generate this for TPT (Table Per Type) tables? 我知道如何与其他表建立关系,但如何为TPT(每种类型的表)表生成此关系?

Description: Let me point out, I am not referring to foreign key relationships. 描述:让我指出,我不是在指外键关系。 With my DbContext I always use Mapping objects for my entities, only because in most cases I prefer to be explicit as opposed to accepting the convention approach. 在我的DbContext中,我总是对实体使用Mapping对象,这仅是因为在大多数情况下,我宁愿明确而不是接受约定。 That being said, all the configuration for my TPT tables are being handled in the EntityTypeConfiguration<SomeEntityClass> classes. 话虽如此,我的TPT表的所有配置都是在EntityTypeConfiguration<SomeEntityClass>类中处理的。

When I define a TPT relationship by creating a new class which derives from another, the ON DELETE CASCADE does not get generated in the SQL constraint, which is the problem. 当我通过创建从另一个派生的新类来定义TPT关系时,SQL约束中不会生成ON DELETE CASCADE ,这就是问题所在。

Have a look at the following code... 看看下面的代码...

  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.
                                      */
    }

The above code is really simple. 上面的代码非常简单。 I have 2 types and they are correctly create in the database. 我有2种类型,它们是在数据库中正确创建的。 If I create a new OtherPerson and save to the database it correctly creates 2 records, 1st a record in the People table and another in the OtherPeople table with a shared primary key which is also the foreign key from OtherPeople to People. 如果我创建一个新的OtherPerson并将其正确保存到数据库中,则它会正确创建2条记录,第1条记录在People表中,另一条记录在OtherPeople表中,并具有共享的主键,该主键也是从OtherPeople到People的外键。 Now, the DbContext or EF rather, correctly deletes both records if I delete the OtherPerson within my code. 现在,的DbContext或EF相当,正确地同时删除记录,如果我在我的代码中删除OtherPerson。 However, should I delete the record directly from the database, an orphan record is left behind in the People table. 但是,如果我直接从数据库中删除该记录,则“ People表中将留下一个孤立记录。

So, how do I get the ON DELETE CASCADE to be specified for the foreign key constraints generated for base tables using the fluent api? 那么,如何使用流利的api获取为基表生成的外键约束指定的ON DELETE CASCADE

Sorry the question is so long but I just wanted to describe the best I could my problem. 抱歉,问题很长,但我只想描述我所能解决的最好问题。 Thanks in advance. 提前致谢。

Now, the DbContext or EF rather, correctly deletes both records if I delete the OtherPerson within my code. 现在,的DbContext或EF相当,正确地同时删除记录,如果我在我的代码中删除OtherPerson。 However, should I delete the record directly from the database, an orphan record is left behind in the People table. 但是,如果我直接从数据库中删除该记录,则“人”表中将留下一个孤立记录。

You seem to say that you want to delete a record from the OtherPeople table (derived entity) and cascading delete should ensure that the corresponding record in the People table (base entity) will be deleted as well. 您似乎想说要从OtherPeople表(派生的实体)中删除一条记录,而级联删除应确保People表(基本实体)中的相应记录也将被删除。

But this is the wrong direction. 但这是错误的方向。 EF creates a relationship and foreign key constraint which goes from the base entity table to the derived entity table, so: The PK table is People and the FK table is OtherPeople . EF创建一个从基本实体表到派生实体表的关系和外键约束,因此:PK表是People ,FK表是OtherPeople With a cascading delete on this relationship you could only ensure that an OtherPeople record is deleted when the corresponding People record will be deleted, not the other way around. 使用此关系的级联删除,您只能确保在删除相应的People记录时删除OtherPeople记录,而不是相反。

This relationship alone - also without cascading delete - makes sure that you cannot get orphan records in the OtherPeople table because it would violate the FK constraint. 单独的这种关系(也没有级联删除)确保了您无法在OtherPeople表中获得孤立记录,因为它会违反FK约束。 (You cannot delete a Person without the related OtherPerson .) (如果没有相关的OtherPerson则不能删除一个Person 。)

For your special purpose you would actually need a second FK constraint in the database where PK table is OtherPeople and the FK table is People . 为了您的特殊目的,您实际上需要在数据库中使用第二个FK约束,其中PK表是OtherPeople ,而FK表是People This relationship isn't created by EF TPT mapping at all and it also would only work if the PK on People is not an identity (at least in SQL Server). 这种关系根本不是由EF TPT映射创建的,并且只有在People上的PK不是身份(至少在SQL Server中)时,它也才起作用。 But it is an identity in your model. 但这是您模型中的一个身份。 So you can't even create this relationship with cascading delete in the database, not to mention with EF. 因此,您甚至无法通过在数据库中级联删除来创建这种关系,更不用说使用EF了。

Back to the relationship which EF actually creates in the database (which is not the one you want with cascading delete) I don't think that there is a mapping option in EF Code-First which would allow you to control the relationship needed for TPT mapping. 回到EF实际上在数据库中创建的关系(这不是您希望进行级联删除的关系),我认为EF Code-First中没有映射选项,该选项允许您控制TPT所需的关系映射。 The only way is to do it directly in the database or - if you want to generate the database from your Code-First model - write a raw SQL statement (which sets up the cascading delete) in a custom initializer and send this to the database after all tables and relationships have been created. 唯一的方法是直接在数据库中执行此操作,或者-如果要从Code-First模型生成数据库,请在自定义初始化程序中编写原始SQL语句(用于设置级联删除)并将其发送到数据库在创建所有表和关系之后。

Somehow in the database People is like Order and OtherPeople is like OrderItem - just not a 1-to-* but a 1-to-0..1 relationship. 在数据库中,“ People就像“ Order而“ OtherPeople就像“ OrderItem -不仅不是1-to-*而是1-to-0..1关系。 What you want is that the parent Order is deleted if the child OrderItem is deleted which means that the dependent will delete the principal. 您想要的是,如果删除子OrderItem则删除父Order ,这意味着依赖项将删除主体。

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

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