你是对的,只给关系的两侧之一一个外键。我首先认为双方都需要一个可为空的外键。但是,如果您这样做,那么事件 1 可能具有记录 2 的外键和事件 3 的外键以及记录 4 的外键,等等。
显然,在这些情况下,只有双方中的一方应该有外键。
查看配置一对零或一关系,我看到以下内容就足够了:
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; }
}
和 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);
}
}
fluent API 通知模型构建器每个 Record 有零个或一个 Event,有零个或一个 Record。记录被声明为依赖。这确保了 Record 在这个关系中会有外来的。
请注意,我不必添加任何其他属性。因为我遵循了代码优先约定实体框架能够检测到主键和表之间的关系。
我能够添加:没有记录的事件、没有事件的记录、有记录的事件和有事件的记录:
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();
}