You were correct, giving only one of the two sides of the relation a foreign key. I first thought that both sides needed a nullable foreign key. However, if you would do that, then Event 1 could have foreign key to Record 2 with a foreign key to Event 3 with a foreign key to Record 4, etc.
Apparently in these situations, only one of the two sides should have a foreign key.
Looking at configure one-to-zero-or-one relation, I see the following is enough:
class Event
{
public long Id { get; set; }
public string Name { get; set; }
// Every Event has zero or one Record
public virtual Record Record { get; set; }
}
class Record
{
public long Id { get; set; }
public string Name { get; set; }
// Every Record has zero or one Event
public virtual Event Event { get; set; }
}
And the DbContext:
class OneToOneContext : DbContext
{
public OneToOneContext(): base("OneToOneDemo"){}
public DbSet<Event> Events { get; set; }
public DbSet<Record> Records { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Record>()
.HasOptional(record => record.Event)
.WithOptionalDependent(ev => ev.Record)
.WillCascadeOnDelete(false);
}
}
The fluent API informs the model builder that every Record has zero or one Event, with zero or one Record. The Record is declared dependent. This ensures that Record will have the foreign in this relation.
Note that I didn't have to add any other Attributes. Because I followed the code first conventions entity framework was able to detect the primary keys and the relation between the tables.
I was able to add: Event without Record, Record without Event, Event with Record and Record with Event:
using (var dbContext = new OneToOneContext())
{
dbContext.Events.Add(new Event { Name = "Event without Record"});
dbContext.Records.Add(new Record { Name = "Record without Event" });
dbContext.Events.Add(new Event
{
Name = "Event A with Record",
Record = new Record { Name = "Record of Event A" },
});
dbContext.Records.Add(new Record
{
Name = "Record B with Event",
Event = new Event { Name = "Event of Record B" },
});
dbContext.SaveChanges();
}