如何使用EF Code First声明一对多关系?

我正在尝试使用Entity Framework流畅的API 在两个poco之间定义一个简单的一对多关系

~ Team ~ public int TeamId { get; set; } public ICollection TeamMembers { get; set; } // All the team players. Two way nav. public Player CreatedBy { get; set; } // Which player created this team. One way navigation. // Optional. Not all players create a team. ~ Player ~ public int PlayerId { get; set; } public Team Team { get; set; } // The other side of the TeamMembers navigation. 

笔记:

  • 玩家不必在团队中。 (未分配/弃牌)。
  • 一支球队可能没有球员(他们都已离开/退出)。

我认为最接近的是这样的……

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasOptional(x => x.TeamMembers) .WithMany() .WillCascadeOnDelete(false); } 

…哪个不起作用..而且我也不确定如何定义其他导航。

有人可以帮帮忙吗?

我认为这个对象模型正是您所寻找的:

 public class Team { public int TeamId { get; set; } public ICollection TeamMembers { get; set; } public Player CreatedBy { get; set; } } public class Player { public int PlayerId { get; set; } public Team Team { get; set; } } public class Context : DbContext { public DbSet Players { get; set; } public DbSet Teams { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasOptional(p => p.Team) .WithMany(t => t.TeamMembers) .Map(c => c.MapKey("TeamId")); // Or alternatively you could start from the Team object: modelBuilder.Entity() .HasMany(t => t.TeamMembers) .WithOptional(p => p.Team) .Map(c => c.MapKey("TeamId")); } } 

顺便说一下,您使用的以下流畅的API代码不正确:

 ...HasOptional(x => x.TeamMembers) 

因为TeamMembers是一个集合,并且HasOptional方法不能使用它,它总是必须使用单个对象调用。

更新 – HasRequired与HasOptional:

虽然他们都建立了一个关联,但他们提供的结果略有不同,并且有不同的要求:

  • 如果它是FK关联(FK属性在依赖对象上公开),那么当使用HasRequired和Code First将抛出时,它在使用HasOptional和非可空类型时必须是可空类型。

  • Code First将在使用HasRequired方法时自动切换级联删除。

  • 另一个区别是删除时的EF运行时行为。 考虑一种情况,我们想要删除主要对象(例如Team ),同时它具有依赖对象(例如Player )并且关闭级联删除。 使用HasOptional EF运行时将静默地将依赖的FK列更新为null,而使用HasRequired EF将抛出并要求您显式删除依赖对象或将其与另一个主体对象相关联(如果您想尝试此操作,则应注意这两者必须在上下文中加载主对象和从属对象,以便EF跟踪它们。

我已经能够通过这样的方式自动完成这项工作:

  public class Team { public int TeamId { get; set; } ... public virtual ICollection Players { get; set; } } 

但是当你说“不起作用”时,你必须更具体地说明你的意思。 究竟什么不起作用? 您收到错误消息了吗? 如果是这样,它是什么? Player对象的Team属性是否始终返回null?