在EF Core数据库上使用复合主键拆分表

时间:2019-06-25 10:27:28

标签: c# .net entity-framework-core

我正在尝试在具有复合主键的EF Core存储库中拆分表。但是它生成一个InvalidOperationException,表示它无法在派生表上找到主键。

“实体类型'DetailedOrder'需要定义主键。'

为了对其进行测试,我从EntityFramework.Docs repository中提取了用于表拆分的示例代码,并对其进行了修改,使其包括复合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 个答案:

答案 0 :(得分:3)

  

实体类型'DetailedOrder'需要定义主键。

必须为所有实体明确定义(复合)PK,而EF Core naming conventions无法自动导出PK。该示例使用的是名为 "paths": { "rxjs/*": ["node_modules/rxjs/*"], } 的PK,这就是为什么它不需要其他配置的原因。

使用表拆分的已发布模型的正确配置应如下所示:

Id

实际上,规则的一对一关系和表拆分之间的唯一区别是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 }); }); 流利配置为主体和从属实体指定了一张相同的表。实体配置的其他部分应该与没有表拆分的情况相同。