Splitting tables with composite primary key on EF Core database

.net c# entity-framework-core

Question

I'm trying to split a table in an EF Core repository which has a composite primary key. But its generating an InvalidOperationException saying that it can't find a primary key on the derived table.

'The entity type 'DetailedOrder' requires a primary key to be defined.'

To test it, I took the sample code for table splitting from the EntityFramework.Docs repository and modified it to include a composite PK:

public class Order
{
    public int OrderId { get; set; }
    public int Rev { get; set; }
    public OrderStatus Status { get; set; }
    public DetailedOrder DetailedOrder { get; set; }
}

public class DetailedOrder : Order
{
    public string BillingAddress { get; set; }
    public string ShippingAddress { get; set; }
    public byte[] Version { get; set; }
}

public class TableSplittingContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<DetailedOrder> DetailedOrders { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer(@"Server = 20.0.5.64\\SQLEXPRESS; Database=EFSamples;User Id = cp; Password=crest1*");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<DetailedOrder>()
                        .ToTable("Orders")
                        .HasBaseType((string)null)
                        .Ignore(o => o.DetailedOrder);

        modelBuilder.Entity<Order>(
                entity =>
                    {
                        entity.HasKey(ck => new { Id = ck.OrderId, ck.Rev });
                        entity.ToTable("Orders")
                            .HasOne(o => o.DetailedOrder).WithOne()
                            .HasForeignKey<Order>(o => new { Id = o.OrderId, o.Rev });
                    });

    }
}
1
2
6/25/2019 12:03:44 PM

Accepted Answer

The entity type 'DetailedOrder' requires a primary key to be defined.

The (composite) PK must be explicitly defined for all entities where the PK cannot be derived automatically by the EF Core naming conventions. The sample is using a PK named Id, that's why it doesn't need additional configuration.

The correct configuration of the posted model with table splitting should be like this:

modelBuilder.Entity<DetailedOrder>(entity =>
{
    entity.HasBaseType((string)null)
        .Ignore(o => o.DetailedOrder);
    entity.HasKey(o => new { o.OrderId, o.Rev }); // <--
    entity.ToTable("Orders");
});

modelBuilder.Entity<Order>(entity =>
{
    entity.HasKey(o => new { o.OrderId, o.Rev }); // <--
    entity.ToTable("Orders");
    entity.HasOne(o => o.DetailedOrder).WithOne()
        .HasForeignKey<Order>(o => new { Id = o.OrderId, o.Rev });
});

In fact the only difference between the reqular one-to-one relationship and table splitting is the ToTable fluent configuration specifying one and the same table for the principal and dependent entity. The other parts of the entity configuration should be the same as with no table splitting.

3
6/25/2019 11:56:07 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow