复合外键作为主键

Composite foreign key as primary key

我目前正在将 EF Core 3.0 代码优先实体迁移到干净的架构方法。

在 EF Core 3.0 中这工作正常:

namespace SmartCom.Models
{
    public class branch
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [MaxLength(128)]
        public virtual string CompanyId { get; set; }

        [MaxLength(128)]
        public string AddressId { get; set; }

        public DateTime CreatedDate { get; set; }

        public int RefNo { get; set; }

        [ForeignKey("AddressId")]
        public address Address { get; set; }
    }
}

在数据库上下文中

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<branch>()
  .HasKey(c => new { c.CompanyId, c.BranchId });

通过干净的架构,我将实体业务逻辑与持久性分离如下:

  1. 没有持久化设置的业务逻辑模型;
namespace SmartComCA.CoSec.Domain.Entities
{
    public class Branch
    {
        public virtual Company Company { get; set; }
        public Address Address { get; set; }
        public DateTime CreatedDate { get; set; }
        public int RefNo { get; set; }
    }
}
  1. 基础设施项目中的持久性配置:
namespace SmartComCA.CoSec.Infrastructure.Persistence.Configuration
{
    public class BranchConfiguration : IEntityTypeConfiguration<Branch>
    {
        public void Configure(EntityTypeBuilder<Branch> builder)
        {
            //builder.HasKey(t => new { t.Company, t.Address});

            builder.HasOne(t => t.Company).WithMany()
                .HasForeignKey("CompanyId");

            builder.HasOne(t => t.Address).WithMany()
                .HasForeignKey("AddressId");

            builder.ToTable("branch");
        }
    }
}

这可以编译但在添加迁移期间失败。如何在持久性从业务逻辑中抽象出来的干净架构中将复合外键指定为主键?

您可以用 shadow properties 替换显式属性。您已经使用 HasForeignKey fluent API 间接完成了这些操作,但以下是与原始定义相匹配的显式定义,它还正确配置了字符串数据类型的最大长度:

builder.Property<string>("CompanyId")
    .IsRequired()
    .HasMaxLength(128);

builder.Property<string>("BranchId")
    .IsRequired()
    .HasMaxLength(128);

然后你就可以定义复合PK使用shadow 属性 names:

builder.HasKey("CompanyId", "BranchId");

但请注意,影子 PK 会对更新和删除等操作施加一些 limitations/requirements,因为它们需要加载相关对象而不仅仅是它们的键。