Since you don't indicate in which EF version you're using let's look at the two current versions, EF 6.2.0 and EF-core 2.2.4.
With EF6, it's easy. The mapping...
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);
...produces the following database model (ignoring indexes):
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])
)
....in which the fields with _ are foreign keys, one of which can have cascaded delete.
With ef-core, it's not so straightforward, even buggy, seemingly. The first impulse is the EF6 equivalent:
modelBuilder.Entity<A>().HasOne(a => a.B1).WithMany();
modelBuilder.Entity<A>().HasOne(a => a.B2).WithMany();
modelBuilder.Entity<B>().HasOne(b => b.A1).WithMany();
But the generated model isn't what one would expect:
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;
One of the A-B associations is interpreted as 1:1. In my opinion that's a bug. The WithMany instruction shouldn't leave any room for interpretation. Two seemingly identical mappings produce quite different database relationships. That can't be right.
That said, it's easy (but shouldn't be necessary) to get EF on the right track by naming the FK columns:
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);
Producing (ignoring indexes):
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;
Note that the foreign key fields must be set required explicitly (if they are). Well, that's just an implementation detail.
Aproperties inB(the one it reference and the other two that reference it) and then 3Bproperies inA(the two it references and the other one that references it).