Reputation: 23
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:
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; }
}
}
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?
Upvotes: 2
Views: 1359
Reputation: 205899
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.
Upvotes: 2