Вопрос состоит из двух частей:
TL; DR: Пусть EF сделает это за вас.
Во-первых: пусть EF выполняет отношения
Короче говоря, свойство идентификации - это то, что БД использует для управления выделенным столбцом идентификатора, поэтому он не зависит от чего-либо внешнего для идентификации каждой строки, поэтому класс bankAccount нуждается в собственном поле идентификатора, чтобы иметь свойство идентификации; теперь, если вы попытаетесь указать EF вручную, как делать отношения, как вы делаете с строкой
HasOne(b => b.Customer).WithOne(c => c.BankAccount).HasForeignKey<BankAccount>(f => f.Id);
то, что вы делаете, - это переопределение внутренней логики самого EF, и в этом случае вы сообщаете EF, что идентификатор банковского счета - это поле, которое ссылается на клиента, что не так, и поэтому EF пытается удалить IDENTITY из поле 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 удалить свойство Identity
(но это не решит проблему внешнего ключа исходного вопроса).
Во-первых, просто напомним: чтобы изменить свойство идентификации, менеджер БД (mysql, sqlserver и т. Д.) Всегда будет просить вас удалить и воссоздать таблицу, потому что это поле является сердцем таблицы. Поэтому вам нужно обмануть EF, чтобы он нашел обходной путь.
Добавьте второй элемент Id в класс модели с очевидным именем, например duplicateId
.
public class BankAccount
{
public int Id { get; set; }
public int duplicateId { get; set; }
...
}
ЭТО УЮЛКА;)
В классе, в котором вы реализовали интерфейс DbContext
, добавьте следующий метод, в котором вы указываете ef, какое поле вы хотите использовать в качестве первичного ключа:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BankAccount>().HasKey(x => new { x.duplicateId });
}
Добавьте новую миграцию с $ dotnet ef migrations add ModelIdChange1
, поскольку при этом изменяется первичный ключ таблицы, и метод миграции Up
должен выглядеть примерно так:
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");
...
}
Затем выполните обновление базы данных с помощью $ dotnet ef database update
(эти команды могут отличаться, используйте любой синтаксис, который вы уже использовали ранее).
(НЕОБЯЗАТЕЛЬНО) Если вам нужно сохранить исходные идентификаторы, убедитесь, что они сохранились, или просто выполните «грязное» обновление таблицы, чтобы скопировать данные из поля Id
в duplicateId
.
Теперь исходное поле Id
можно удалить или обновить, поэтому просто удалите исходное поле из модели:
public class BankAccount
{
public int duplicateId { get; set; }
...
}
Если вы все еще пытаетесь принудительно выполнить исходную команду, которая связывает идентификатор BankAccount Id с идентификатором клиента, она должна сработать, если вы запустите команду на этом этапе, но, пожалуйста, не делайте этого. em>
И добавьте новую миграцию с $ dotnet ef migrations add ModelIdChange2
, а затем выполните обновление базы данных с $ dotnet ef database update
, которое удалит исходный столбец Id
и оставит duplicateId
в качестве первичного ключа.
Теперь модель выглядит почти как исходная, но с новым столбцом идентификаторов вы можете оставить это так или просто переименовать поле обратно с duplicateId
на Id
в классе BankAccount следующим образом:
public class BankAccount
{
public int Id { get; set; }
...
}
и выполните $ dotnet ef migrations add ModelIdChange3
, а затем выполните обновление базы данных с помощью $ dotnet ef database update
.
person
unJordi
schedule
21.05.2021
One Customer One BankAccount
, поэтому идентификатор в сущности «Клиент» можно использовать как FK и первичный ключ в сущности BankAccount. - person Kgn-web   schedule 21.11.2018