EF Core: Using ID as Primary key and foreign key at same time

点点圈 提交于 2019-12-06 05:36:10

Using attributes only, without FluentAPI:

public abstract class DtoBase
{
    [Key]
    public Guid ID { get; protected set; }
}

public class PersonDto : DtoBase
{
    [InverseProperty("Person")]
    public ProspectDto Prospect { get; set; }
}

public class ProspectDto : DtoBase
{
    [ForeignKey("ID")]           // "magic" is here
    public PersonDto Person { get; set; } = new PersonDto();
}

I don't know what is equivalent of ForeignKey in FluentAPI. All other (Key and InverseProperty) are configurable, but why use two methods instead one.

Code above generates following migration code:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "Persons",
        columns: table => new
        {
            ID = table.Column<Guid>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Persons", x => x.ID);
        });

    migrationBuilder.CreateTable(
        name: "Prospects",
        columns: table => new
        {
            ID = table.Column<Guid>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Prospects", x => x.ID);
            table.ForeignKey(
                name: "FK_Prospects_Persons_ID",
                column: x => x.ID,
                principalTable: "Persons",
                principalColumn: "ID",
                onDelete: ReferentialAction.Cascade);
        });
}

Looks very close to what you need.

Here is the FluentAPI equivalent of @dmitry's solution:

// Model classes:
public abstract class DtoBase
{
    public Guid ID { get; protected set; }
}

public class PersonDto : DtoBase
{
    public ProspectDto Prospect { get; set; }
}

public class ProspectDto : DtoBase
{
    public PersonDto Person { get; set; } = new PersonDto();
}

-------------------------------------------------------------------

// DbContext's OnModelCreating override:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasOne(p => p.Person).WithOne().HasForeignKey<ProspectDto>(p => p.ID);
}

If you model the relationship as one:one, EF will automatically use the PK of the principal as FK for the dependent.

 ModelBuilder.Entity<ProspectDto>().HasRequired(p => p.Person).WithRequiredDependent();

Please note that ProspectDto will still have an ID column on the DB (inherited from DtoBase), but the FK relationship will be between ProspectDto.ID and PersonDto.ID and there should be no ProspectDto.PersonId column.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!