如何在Entity Framework 6 Code First中创建多个1:1外键关系?

时间:2015-03-10 20:28:08

标签: c# entity-framework ef-code-first entity-framework-6 one-to-one

让我假装我有三个表,每个表都有一个名为Id的主键:

TableA
------
Id

TableB
------
Id

TableC
-----
Id

意图是每个实体彼此具有一对一的导航属性,以便我可以在给定任何实体的任何方向上导航。很遗憾,我还没有找到[Key][ForeignKey]和导航属性的组合,每个实体允许此多次。

例如,这有效(实体框架认为TableA是1:1关系中的主体):

public class TableA
{
    [Key]
    [Required]
    public Guid Id { get; set; }

    public virtual TableB TableB { get; set; }
    public virtual TableC TableB { get; set; }
}

public class TableB
{
    [Key]
    [ForeignKey("TableA")]
    [Required]
    public Guid Id { get; set; }

    public virtual TableA TableA { get; set; }
}

但这不起作用:

public class TableB
{
    [Key]
    [ForeignKey("TableA,TableC")] // The constructor documentation says this will work, but at runtime it throws an exception
    [Required]
    public Guid Id { get; set; }

    public virtual TableA TableA { get; set; }

    public virtual TableC TableC { get; set; }
}

也不是这样:

public class TableB
{
    [Key]
    [Required]
    public Guid Id { get; set; }

    [ForeignKey("Id")]
    public virtual TableA TableA { get; set; }

    [ForeignKey("Id")]
    public virtual TableC TableC { get; set; }
}

如何使用属性来允许这些关系?目前,如果我想从TableC导航到TableB,我必须浏览TableA,导致额外的不必要的数据库查找。似乎实体框架想要强制一种可能没有的层次关系。

1 个答案:

答案 0 :(得分:1)

我认为你需要的是这样的模型:

public class TableA
{
    [Key]
    public Guid Id { get; set; }

    public virtual TableB TableB { get; set; }
    public virtual TableC TableC { get; set; }
}
public class TableB
{
    [Key]
    [ForeignKey("TableA")]
    public Guid Id { get; set; }

    public virtual TableA TableA { get; set; }

    public virtual TableC TableC { get; set; }
}

public class TableC
{
    [Key]
    [ForeignKey("TableB")]
    public Guid Id { get; set; }

    public virtual TableB TableB { get; set; }

    [Required]
    public virtual TableA TableA { get; set; }
}

您不需要在TableC实体中为TableB导航属性指定FK属性,因为TableB是B和C之间关系的主体。

更新

尝试删除Required数据注释并以这种方式配置关系,覆盖上下文中的OnModelCreating方法:

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
        modelBuilder.Entity<TableA>().HasOptional(a => a.TableC).WithOptionalPrincipal(c => c.TableA);

        base.OnModelCreating(modelBuilder);
  }