Entity Framework Table Per Class Inheritance

2019-08-12 03:30发布

问题:

I am trying to implement a history table for an entity in EF6, code first.

I figured there would be a way to do this with inheritance. The history table, which is a derived type of the actual table entity, just containing straight copies of all the properties. Along with an edit to the key.

My code first table entity config for Booking.

public class BookingEntityConfiguration
    : EntityTypeConfiguration<Booking>
{
    public BookingEntityConfiguration()
    {
        Property(b => b.BookingId).HasColumnOrder(0);
        HasKey(b => new { b.BookingId });

        HasOptional(b => b.BookingType)
            .WithMany()
            .HasForeignKey(c => c.BookingTypeId);
    }
}

My code first table entity config for BookingHistory.

public class BookingHistoryTypeEntityConfiguration
    : EntityTypeConfiguration<BookingHistory>
{
    public BookingHistoryTypeEntityConfiguration()
    {
        Property(b => b.BookingId).HasColumnOrder(0);
        Property(b => b.BookingVersion).HasColumnOrder(0);
        HasKey(b => new { b.BookingId, b.BookingVersion });
    }
}

Where

public class BookingHistory : Booking { }

My BookingHistory table never gets generated in the contexts associated database, which includes these references to the table entities:

public DbSet<Booking> Bookings { get; set; }
public DbSet<BookingHistory> BookingHistories { get; set; }

Is there any simple way to achieve what I want? Which is the derived entity (history table) generates a table that contains the same column fields as the base class entity, but with a change of key.

I appreciate my code above is pretty naive, but I can't seem to find a blog post of similar to help.

回答1:

The best way is to have a base type from which both the entity and its history entity inherit:

public class BookingsContext : DbContext
{

    public DbSet<Booking> Bookings { get; set; }
    public DbSet<BookingHistory> BookingHistories { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BookingBase>()
            .HasKey(p => p.BookingId)
            .Property(p => p.BookingId)
                       .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<Booking>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("Booking");
            });

        modelBuilder.Entity<BookingHistory>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("BookingHistory");
            });
    }
}

By ToTable you specify that both entities should be mapped to different tables. On top of that, MapInheritedProperties tells EF to mapp all properties from the base type to this table as well. the result is two completely independent tables that can be addressed by two separate DbSet properties.