这个问题有两个部分的答案:
简而言之,请让EF为您完成。
首先:让EF处理关系
简单来说,身份属性是数据库用于管理专用ID列的属性,因此它不依赖于外部任何东西来识别每一行数据。因此,bankAccount类需要其自己的Id字段来具有标识属性;现在,如果您试图手动告诉EF如何处理关系,就像使用以下代码:
HasOne(b => b.Customer).WithOne(c => c.BankAccount).HasForeignKey<BankAccount>(f => f.Id)
你所做的是覆盖了EF本身的内部逻辑,在这种情况下,你告诉EF银行账户ID是引用客户的字段,但实际上不是。因此EF尝试从银行账户模型中删除ID字段的IDENTITY属性,但这只是因为
你告诉它银行账户ID应该与客户ID相同。
我认为我理解你想表达的一对一关系,但如果客户想再开一个银行账户会发生什么呢?D:
相反,你应该保留
int CustomerId
字段并删除
Customer Customer
字段,不仅更清晰,而且EF将会自动识别两个类之间的关系,只要有一个名为
Customer
的类和一个
Id
字段即可。
public int CustomerId { get; set; } //keep
public Customer Customer { get; set; } //delete
因此,客户可以在银行开立任意数量的账户,而表格不会受到影响,EF知道该怎么做。
它会自动生成相应的外键并将其添加到迁移文件中,就像这样:
migrationBuilder.AddForeignKey(
name: "FK_BankAccount_Customer_CustomerId",
table: "BankAccount",
column: "CustomerId",
principalTable: "Customer",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
这将反映出一对多的关系,这很好。
现在回答问题,如果您仍然想删除属性:
第二步:强制EF删除标识属性
(但它不会解决原问题的外键问题).
首先,简单回顾一下:要更改标识属性,数据库管理器(mysql、sqlserver等)总是会要求您删除并重新创建表,因为该字段是表的核心。所以您需要欺骗EF为您做一个变通。
Add a second Id element to the model class with an obvious name like duplicateId
.
public class BankAccount
{
public int Id { get; set; }
public int duplicateId { get; set; }
...
}
THIS IS THE TRICK ;)
In the class there you implemented the DbContext
interface, add the following method where you tell the ef which field you want the primary key to be:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BankAccount>().HasKey(x => new { x.duplicateId });
}
Add a new Migration with $ dotnet ef migrations add ModelIdChange1
, since this changes the primary key of the table and the migration Up
method should look lile this:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_BankAccount",
table: "BankAccountTableName");
migrationBuilder.AddColumn<int>(
name: "duplicateId",
table: "BankAccountTableName",
type: "int",
nullable: false,
defaultValue: 0)
.Annotation("SqlServer:Identity", "1, 1");
migrationBuilder.AddPrimaryKey(
name: "PK_BankAccount",
table: "BankAccountTableName",
column: "duplicateId");
...
}
Then do the database update with $ dotnet ef database update
(these commands may vary, use whatever syntax you already used before).
(OPTIONAL) If you are need to preserve the original IDs, check that they got preserved or simply do a dirty update on the table to copy the data from the Id
field into the duplicateId
.
Now the original Id
field is free to be deleted or updated, so go ahead and just delete de original field from the model:
public class BankAccount
{
public int duplicateId { get; set; }
...
}
如果你仍然在尝试强制执行将银行账户 ID 与客户 ID 相关联的原始命令,那么在此步骤运行该命令可能会起作用,但请不要这样做。
And add a new Migration with $ dotnet ef migrations add ModelIdChange2
, and then do the database update with $ dotnet ef database update
, which deletes the original Id
column and leaves duplicateId
as the primary key.
Now, the model looks almost the Original one but with a new identity column, you can leave it like that or just rename the field back from duplicateId
to Id
in the BankAccount class like this:
public class BankAccount
{
public int Id { get; set; }
...
}
and do $ dotnet ef migrations add ModelIdChange3
, and then do the database update with $ dotnet ef database update
.