如何使用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?