实体框架实体与一对多和一对一?

时间:2014-01-03 07:08:13

标签: c# entity-framework

以下是我试图在Entity Framework代码优先工作的父/子关系的简化示例。父项列表包含子项,其中一项被选为默认项:

public class Parent
{
    [Key]
    public int Id { get; set; }
    public virtual Child DefaultChild { get; set; }          // One-to-One
    public virtual ICollection<Child> Children { get; set; } // One-to-Many
}

public class Child
{
    [Key]
    public int Id { get; set; }
    [Required]
    public virtual Parent Parent { get; set; }
}

当我运行实体框架的add-migration命令时,它将Id for Child设置为键,而不是使其成为IDENTITY,而是使用对父ID的外键引用。

我尝试在DbContext上执行以下操作:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Parent>().HasOptional(p => p.DefaultChild).WithRequired(c => c.Parent);
    modelBuilder.Entity<Parent>().HasMany(p => p.Children).WithRequired(c => c.Parent);
    base.OnModelCreating(modelBuilder);
} 

但是,它会抛出此错误:Schema specified is not valid. Errors: The relationship 'Sample.Presentation.DataAccess.Parent_DefaultChild' was not loaded because the type 'Sample.Presentation.DataAccess.Child' is not available.

你应该如何处理这些关系?

我知道我可以向Child添加一个布尔标志(例如IsDefault)并删除父级的DefaultChild关系。但是,如果可能的话,我想避免这种情况。


编辑:我发现此info on StackOverflow使用WithOptionalPrincipal,但是,它会在子级上创建一个额外的ParentId字段,而不是在父级上创建ChildId?不是我想要的。


修改:根据评论中的建议添加了DatabaseGenerated。这就是迁移输出的内容:

CreateTable(
    "dbo.Children",
    c => new
       {
           Id = c.Int(nullable: false, identity: true),
           Parent_Id = c.Int(nullable: false),
       })
       .PrimaryKey(t => t.Id)
       .ForeignKey("dbo.Parents", t => t.Id)  // <== I don't want this!
       .ForeignKey("dbo.Parents", t => t.Parent_Id, cascadeDelete: true)
       .Index(t => t.Id)
       .Index(t => t.Parent_Id);

 CreateTable(
    "dbo.Parents",
    c => new
       {
           Id = c.Int(nullable: false, identity: true)  // <== I expect DefaultChildId after this
       })
       .PrimaryKey(t => t.Id);  // <== and a foreign key referencing Child.Id

1 个答案:

答案 0 :(得分:1)

一对一和一对多关系不能在两个实体上共存。因为EF要求一对一关系的从属端(应该有外键)的密钥必须是主要结束的外键。这条规则确保一对一的关系有效。我认为这是一个可用的解决方案,可以将属性IsDefault添加到子实体。