简体   繁体   中英

Composite foreign key as primary key

I am currently migrating EF Core 3.0 code-first entity to clean architecture approach.

In EF Core 3.0 this works fine:

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; }
    }
}

At the DB context

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

With clean architecture, I separated entity business logic from persistence as follows:

  1. Business logic model without persistence settings;
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. Persistence configuration in Infrastructure project:
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");
        }
    }
}

This compiles but fails during add-migration. How do I specify composite foreign key as primary key in clean architecture where persistence is abstracted from business logic?

You can replace the explicit properties with shadow properties . Which you already did indirectly with HasForeignKey fluent API, but following is the explicit definition matching the original definition which also correctly configures the max length for string data types:

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

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

Then you can define the composite PK using the shadow property names:

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

But please note that having shadow PK imposes some limitations/requirements for operations like update and delete, since they would require having the loaded related objects rather than just their keys.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM