Search code examples
c#entity-frameworktable-per-type

Cascade delete child record using EF's TPT fluent syntax


I'm trying to get a basic example of TPT working. Most references discuss TPT in general, and how it works, but don't go into the actual fluent mapping details. This is what I have so far:

public abstract class Parent {
  public Parent() { }
  public int Id { get; set; }
  // other properties...
}

public class Child : Parent {
  public Child() : base() { }
  // other properties...
}

public class MyContext : DbContext {
  protected override void OnModelCreating(DbModelBuilder modelBuilder) {

    var p = modelBuilder.Entity<Parent>();
    p.ToTable("Parent");
    p.HasKey(m => m.Id);
    p.Property(m => m.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

    var c = modelBuilder.Entity<Child>();
    c.ToTable("Child");
    //c.HasKey(m => m.Id);                                     // needed?
    //c.Property(m => m.Id).HasColumnName("Id").IsRequired();  // needed?

  }
}

Is this all that I need to do? Is there a reference example for this specific case somewhere?

UPDATE:
Thanks to the comments, I've discovered that this is correct, and that things are mapped by convention.

What I've discovered though is that a child record is not cascade deleted automatically when a parent record is deleted. I can change this via script, but I want to use an EF approach. How do I configure the child to do that?


Solution

  • From reviewing other questions going way way back, looks like a bug/missing feature. And there's no clear solution... which I've found.

    So unless someone has a better idea, I'll need to create an empty migration, and add the necessary sql statements to force the cascade delete:

    AddForeignKey("dbo.Child", "Id", "dbo.Parent", "Id", true);    // <- true is the trick
    

    ...which generates:

    ALTER TABLE [Child] ADD CONSTRAINT [FK_dbo.Child_dbo.Parent_Id]
    FOREIGN KEY ([Id]) REFERENCES [Parent]([Id]) ON DELETE CASCADE ON UPDATE NO ACTION;
    

    Notice the ON DELETE CASCADE.

    Please tell me if there is a better way? (i.e. one that doesn't require me fiddling with migrations and/or SQL.)