Поскольку вы не указываете, в какой версии EF вы используете, давайте посмотрим на две текущие версии, EF 6.2.0 и EF-core 2.2.4.
С EF6 это легко.Отображение ...
modelBuilder.Entity<A>().HasRequired(a => a.B1).WithMany();
modelBuilder.Entity<A>().HasRequired(a => a.B2).WithMany().WillCascadeOnDelete(false);
modelBuilder.Entity<B>().HasRequired(b => b.A1).WithMany().WillCascadeOnDelete(false);
... создает следующую модель базы данных (без учета индексов):
CREATE TABLE [dbo].[A] (
[ID] [int] NOT NULL IDENTITY,
[B1_ID] [int] NOT NULL,
[B2_ID] [int] NOT NULL,
CONSTRAINT [PK_dbo.A] PRIMARY KEY ([ID])
)
CREATE TABLE [dbo].[B] (
[ID] [int] NOT NULL IDENTITY,
[A1_ID] [int] NOT NULL,
CONSTRAINT [PK_dbo.B] PRIMARY KEY ([ID])
)
...., в которой поля с _
являются чужимиключи, один из которых может каскадно удалять.
С ef-core это не так просто, даже глючно, на первый взгляд.Первый импульс - это эквивалент EF6:
modelBuilder.Entity<A>().HasOne(a => a.B1).WithMany();
modelBuilder.Entity<A>().HasOne(a => a.B2).WithMany();
modelBuilder.Entity<B>().HasOne(b => b.A1).WithMany();
Но сгенерированная модель не соответствует ожиданиям:
CREATE TABLE [B] (
[ID] int NOT NULL IDENTITY,
[A1ID] int NULL,
CONSTRAINT [PK_B] PRIMARY KEY ([ID])
);
CREATE TABLE [A] (
[ID] int NOT NULL,
[B1ID] int NULL,
CONSTRAINT [PK_A] PRIMARY KEY ([ID]),
CONSTRAINT [FK_A_B_B1ID] FOREIGN KEY ([B1ID]) REFERENCES [B] ([ID]) ON DELETE NO ACTION,
CONSTRAINT [FK_A_B_ID] FOREIGN KEY ([ID]) REFERENCES [B] ([ID]) ON DELETE CASCADE
);
ALTER TABLE [B] ADD CONSTRAINT [FK_B_A_A1ID] FOREIGN KEY ([A1ID]) REFERENCES [A] ([ID]) ON DELETE NO ACTION;
Одна из ассоциаций A-B
интерпретируется как 1:1.На мой взгляд, это ошибка.Инструкция WithMany
не должна оставлять места для интерпретации.Два по-видимому идентичных отображения производят совершенно разные отношения базы данныхЭто не может быть правдой.
Тем не менее, легко (но не обязательно), чтобы получить EF на правильном пути, назвав столбцы FK:
modelBuilder.Entity<A>().HasOne(a => a.B1).WithMany().HasForeignKey("B1_ID")
.IsRequired();
modelBuilder.Entity<A>().HasOne(a => a.B2).WithMany().HasForeignKey("B2_ID")
.IsRequired().OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<B>().HasOne(b => b.A1).WithMany().HasForeignKey("A1_ID")
.IsRequired().OnDelete(DeleteBehavior.Restrict);
Производство (игнорирование индексов):
CREATE TABLE [B] (
[ID] int NOT NULL IDENTITY,
[A1_ID] int NOT NULL,
CONSTRAINT [PK_B] PRIMARY KEY ([ID])
);
CREATE TABLE [A] (
[ID] int NOT NULL IDENTITY,
[B1_ID] int NOT NULL,
[B2_ID] int NOT NULL,
CONSTRAINT [PK_A] PRIMARY KEY ([ID]),
CONSTRAINT [FK_A_B_B1_ID] FOREIGN KEY ([B1_ID]) REFERENCES [B] ([ID]) ON DELETE CASCADE,
CONSTRAINT [FK_A_B_B2_ID] FOREIGN KEY ([B2_ID]) REFERENCES [B] ([ID]) ON DELETE NO ACTION
);
ALTER TABLE [B] ADD CONSTRAINT [FK_B_A_A1_ID] FOREIGN KEY ([A1_ID]) REFERENCES [A] ([ID]) ON DELETE NO ACTION;
Обратите внимание, что поля внешнего ключа должны быть установлены обязательными явным образом (если они есть).Ну, это просто детали реализации.