C# 如何首先使用EF代码声明一对多关系?
我试图使用实体框架fluentapi在两个poco之间定义一个简单的一对多关系C# 如何首先使用EF代码声明一对多关系?,c#,.net,entity-framework,C#,.net,Entity Framework,我试图使用实体框架fluentapi在两个poco之间定义一个简单的一对多关系 ~ Team ~ public int TeamId { get; set; } public ICollection<User> TeamMembers { get; set; } // All the team players. Two way nav. public Player CreatedBy { get; set; } // Which player created this team. O
~ Team ~
public int TeamId { get; set; }
public ICollection<User> 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.
~团队~
public int TeamId{get;set;}
公共ICollection团队成员{get;set;}//所有团队成员。双向导航。
公共玩家通过{get;set;}//哪个玩家创建了这个团队。单向导航。
//可选。并不是所有的球员都能组成一支球队。
~Player~
public int PlayerId{get;set;}
公共团队{get;set;}//团队成员导航的另一侧。
注:
- 球员不一定要在一个队里。(未分配/放弃玩家)
- 一个团队可能没有球员(他们都离开了/退出了)
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Team>()
.HasOptional(x => x.TeamMembers)
.WithMany()
.WillCascadeOnDelete(false);
}
public class Team {
public int TeamId { get; set; }
...
public virtual ICollection<Player> Players { get; set; }
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.has可选(x=>x.TeamMembers)
.有很多
.WillCascadeOnDelete(假);
}
这不起作用,我也不知道如何定义其他导航。我已经能够通过这样的操作自动实现这一点:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Team>()
.HasOptional(x => x.TeamMembers)
.WithMany()
.WillCascadeOnDelete(false);
}
public class Team {
public int TeamId { get; set; }
...
public virtual ICollection<Player> Players { get; set; }
}
公共类团队{
public int TeamId{get;set;}
...
公共虚拟ICollection播放器{get;set;}
}
但当你说“不起作用”时,你必须更具体地说明你的确切意思。到底是什么不起作用?您是否收到错误消息?如果是,是什么?玩家对象的团队属性是否总是返回null?我认为这个对象模型就是您要寻找的:
public class Team
{
public int TeamId { get; set; }
public ICollection<Player> 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<Player> Players { get; set; }
public DbSet<Team> Teams { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Player>()
.HasOptional(p => p.Team)
.WithMany(t => t.TeamMembers)
.Map(c => c.MapKey("TeamId"));
// Or alternatively you could start from the Team object:
modelBuilder.Entity<Team>()
.HasMany(t => t.TeamMembers)
.WithOptional(p => p.Team)
.Map(c => c.MapKey("TeamId"));
}
}
因为TeamMembers是一个集合,不能由HasOptional方法使用,该方法始终必须通过单个对象调用
更新-HasRequired与HasOptional:
虽然他们都成立了一个协会,但结果略有不同,要求也有所不同:
- 如果它是FK关联(FK属性在依赖对象上公开),则在使用HasOptional时它必须是可空类型,在使用HasRequired时它必须是不可空类型,否则Code First将抛出
- 使用HasRequired方法时,Code First将自动打开级联删除
- 另一个区别是EF在删除时的运行时行为。考虑一个场景,当它有一个依赖对象(例如<代码>播放器< /代码>)并且级联删除被关闭时,我们想要删除主对象(例如,<>代码>团队/代码>)。使用HasOptional EF,运行时将无声地将dependent FK列更新为null,而使用HasRequired EF,运行时将抛出并要求您显式删除dependent对象或将其与另一个主体对象关联(如果您想尝试这种方法,您应该知道,在这两种情况下,主体对象和从属对象都必须已经加载到上下文中,以便EF能够跟踪它们)
FK属性暴露在依赖对象上
。另外,你能举一个例子,如果你从球队走到球员身上,你可以建立这种关系吗?这个班有一对多的其他班,没问题。不,我的意思是区分EF 4.0FK关联
和EF 3.5独立关联
CreatedBy
不是FK属性,它是一个导航属性,但是如果您在CreatedBy
后面添加PlayerId
之类的property,则PlayerId
将是FK属性,您的关联将成为FK关联(现在它是一个独立的关联)。现在,如果您将PlayerId
定义为int?
,那么您的对象模型中将有一个可为空的FK,可以通过HasOptional
fluent API方法进行配置。您应该使用Map
方法。我已经在我的答案中更新了fluent API代码,向您展示了如何更新。