EF Core:同时使用 ID 作为主键和外键
EF Core: Using ID as Primary key and foreign key at same time
我有两个实体,Prospect
和 Person
,我想做的是使用 Prospect.ID
作为 Prospect
[=41= 上的主键] 作为 PersonID
的外键,我的想法是对两个实体使用相同的 ID,而无需在我的 Prospect
实体上使用 PersonID
。当潜在客户被保存在数据库中时,它会尝试保存一个 PersonID
,即使我的 Prospect
实体上没有这个 属性,我想知道 EF 核心是否支持这种关系。
这是我在模型构建器上得到的:
modelBuilder.Entity<ProspectDto>(builder => { builder.ToTable("Prospects"); builder.HasKey(prospect => prospect.ID); });
modelBuilder.Entity<PersonDto>(builder => { builder.HasOne(p => p.Prospect).WithOne().HasForeignKey<ProspectDto>(pe => pe.ID); });
这是在数据库上执行的操作:
INSERT INTO [Prospects] ([ID], [PersonID]) VALUES (@p421, @p422)
PersonDto
:
public class PersonDto : DtoBase
{
public PersonDto()
{
}
public ProspectDto Prospect { get; set; }
}
ProspectDto
:
public class ProspectDto : DtoBase
{
public ProspectDto()
{
}
public PersonDto Person { get; set; } = new PersonDto();
}
DtoBase
:
public abstract class DtoBase
{
public Guid ID { get; protected set; }
}
谢谢。
如果您将关系建模为 one:one,EF 将自动使用主体的 PK 作为依赖项的 FK。
ModelBuilder.Entity<ProspectDto>().HasRequired(p => p.Person).WithRequiredDependent();
请注意,ProspectDto
仍将在数据库中有一个 ID
列(继承自 DtoBase),但 FK 关系将介于 ProspectDto.ID
和 PersonDto.ID
之间并且不应有 ProspectDto.PersonId
列。
仅使用属性,不使用 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();
}
我不知道 FluentAPI 中 ForeignKey
的等价物是什么。所有其他(Key 和 InverseProperty)都是可配置的,但为什么要使用两种方法而不是一种方法。
上面的代码生成以下迁移代码:
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);
});
}
看起来非常接近您的需要。
这是与@dmitry 的解决方案等效的 FluentAPI:
// 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.Entity<ProspectDto>().HasOne(p => p.Person).WithOne().HasForeignKey<ProspectDto>(p => p.ID);
}
我有两个实体,Prospect
和 Person
,我想做的是使用 Prospect.ID
作为 Prospect
[=41= 上的主键] 作为 PersonID
的外键,我的想法是对两个实体使用相同的 ID,而无需在我的 Prospect
实体上使用 PersonID
。当潜在客户被保存在数据库中时,它会尝试保存一个 PersonID
,即使我的 Prospect
实体上没有这个 属性,我想知道 EF 核心是否支持这种关系。
这是我在模型构建器上得到的:
modelBuilder.Entity<ProspectDto>(builder => { builder.ToTable("Prospects"); builder.HasKey(prospect => prospect.ID); });
modelBuilder.Entity<PersonDto>(builder => { builder.HasOne(p => p.Prospect).WithOne().HasForeignKey<ProspectDto>(pe => pe.ID); });
这是在数据库上执行的操作:
INSERT INTO [Prospects] ([ID], [PersonID]) VALUES (@p421, @p422)
PersonDto
:
public class PersonDto : DtoBase
{
public PersonDto()
{
}
public ProspectDto Prospect { get; set; }
}
ProspectDto
:
public class ProspectDto : DtoBase
{
public ProspectDto()
{
}
public PersonDto Person { get; set; } = new PersonDto();
}
DtoBase
:
public abstract class DtoBase
{
public Guid ID { get; protected set; }
}
谢谢。
如果您将关系建模为 one:one,EF 将自动使用主体的 PK 作为依赖项的 FK。
ModelBuilder.Entity<ProspectDto>().HasRequired(p => p.Person).WithRequiredDependent();
请注意,ProspectDto
仍将在数据库中有一个 ID
列(继承自 DtoBase),但 FK 关系将介于 ProspectDto.ID
和 PersonDto.ID
之间并且不应有 ProspectDto.PersonId
列。
仅使用属性,不使用 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();
}
我不知道 FluentAPI 中 ForeignKey
的等价物是什么。所有其他(Key 和 InverseProperty)都是可配置的,但为什么要使用两种方法而不是一种方法。
上面的代码生成以下迁移代码:
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);
});
}
看起来非常接近您的需要。
这是与@dmitry 的解决方案等效的 FluentAPI:
// 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.Entity<ProspectDto>().HasOne(p => p.Person).WithOne().HasForeignKey<ProspectDto>(p => p.ID);
}