开发者

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 con开发者_JAVA百科straint using the fluent api for base tables? 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?

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. That being said, all the configuration for my TPT tables are being handled in the EntityTypeConfiguration<SomeEntityClass> classes.

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.

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. 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. Now, the DbContext or EF rather, correctly deletes both records if I delete the OtherPerson within my code. However, should I delete the record directly from the database, an orphan record is left behind in the People table.

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?

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. 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.

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. 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.

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. (You cannot delete a Person without the related OtherPerson.)

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. 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). 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.

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. 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.

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. 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜