棘手的实体框架一对一的关系

And*_*rew 4 .net c# mapping entity-framework code-first

我有一个应用程序,记录不同的网球锦标赛事件.它还记录每个事件的获胜者

有问题的两个类是:

public class Event {
  public int EventId { get; set; }
  public string EventName { get; set; }
  public virtual ICollection<Entry> Entries { get; set; }
  public int? WinningEntryId { get; set; }

  [ForeignKey("WinningEntryId")]
  public virtual Entry WinningEntry { get; set; }
}

public class Entry {
  public int EntryId { get; set; }
  public int EventId { get; set; }

  [ForeignKey("EventId")]
  public virtual Event Event { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

请注意,Event.WinningEntryId列可以为空,因为我不想指定获胜者,因为锦标赛可能仍在进行中.

现在,问题是当我运行Update-Database命令时,它会生成以下表:

Entry
 - EntryId
 - EventId
 - Event_EventId

Event
 - EventId
 - WinningEntryId
Run Code Online (Sandbox Code Playgroud)

为什么EF在Event表中生成Event_EventId列?我只是希望Event.WinningEntryId列指向外键关系中的Entry.EntryId列.

我必须以某种方式做错.谁知道我怎么能做到这一点?

dev*_*tal 5

假设你的导航属性:

public virtual Entry WinningEntryId { get; set; }
Run Code Online (Sandbox Code Playgroud)

实际上是被称为WinningEntry:

public virtual Entry WinningEntry { get; set; }
Run Code Online (Sandbox Code Playgroud)

那么实际上看起来你是在建模一对多的关系,而不是一对一的关系.一个事件可以有多个条目,一个条目可以属于一个事件?只是其中一个条目将被标记为获胜条目.

我会考虑不使用数据注释,并坚持使用流畅的API来a)在中心位置管理所有配置,b)不要将持久性问题与域对象混合.

在这种情况下,您可以使用fluent API配置映射,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{     
    modelBuilder.Entity<Event>()
       .HasOptional(ev => ev.WinningEntry)
       .WithMany()
       .HasForeignKey(ev => ev.WinningEntryId)
       .WillCascadeOnDelete(false);

    modelBuilder.Entity<Entry>()
        .HasRequired(en => en.Event)
        .WithMany(ev => ev.Entries)
        .HasForeignKey(en => en.EventId);
}
Run Code Online (Sandbox Code Playgroud)

这将模拟与以下关系:

Events
    EventId (PK)
    EventName
    WinningEventId (FK, null)

Entries
    EntryId (PK)
    EventId (FK, not null)
Run Code Online (Sandbox Code Playgroud)