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

Pur*_*ome 7 .net c# entity-framework

我正在尝试使用Entity Framework流畅的API 在两个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. 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.
Run Code Online (Sandbox Code Playgroud)

笔记:

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

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

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Team>()
        .HasOptional(x => x.TeamMembers)
        .WithMany()
        .WillCascadeOnDelete(false);
}
Run Code Online (Sandbox Code Playgroud)

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

有人可以帮忙吗?

Mor*_*avi 12

我认为这个对象模型正是你要找的:

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"));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

...HasOptional(x => x.TeamMembers)
Run Code Online (Sandbox Code Playgroud)

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

更新 - HasRequired与HasOptional:

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

  • 如果它是一个FK关联(FK属性在依赖对象上公开),那么当使用HasRequired和使用HasRequired或者Code First将抛出时,它必须是可以为空的类型.

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

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