实体框架(代码优先)一对多和一对一关系(有两个实体)。如何?

Mr.*_* MX 5 entity-framework one-to-one one-to-many code-first relationships

我正在尝试使用 EF Code First 来做到这一点:

数据库模型

有区域两个表:用户和区域。一个用户属于一个所需的区域,一个区域可以有零个或一个用户(作为管理员)。然后:

用户 *..1 区域和用户 0..1 区域

用户类:

public class User {
    public int UserId { get; set; }
    public string Name { get; set; }

    [ForeignKey("Area")]
    public int AreaId { get; set; }
    [InverseProperty("Users")]
    public virtual Area Area { get; set; }

    public virtual Area AreaTitular { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

区域类:

public class Area {
    public int AreaId { get; set; }
    public string Name { get; set; }

    public List<User> Users { get; set; }

    [ForeignKey("User")]
    public int? UserId { get; set; }
    [InverseProperty("AreaTitular")]
    public virtual User User{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)

以及 update-database 命令上的错误:

无法确定类型“TestEntityFrameworkCodeFirst.Model.Area”和“TestEntityFrameworkCodeFirst.Model.User”之间关联的主体端。必须使用关系流畅 API 或数据注释显式配置此关联的主体端。

任何帮助将不胜感激:)

我不完全确定这是否可以:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
    modelBuilder.Entity<Area>()
        .HasOptional(i => i.User)
        .WithOptionalDependent();
    base.OnModelCreating(modelBuilder);
}
Run Code Online (Sandbox Code Playgroud)

刚刚在 Context 类的 OnModelCreating 上添加了这个。这是它在 SQL Server 中的样子:

数据库

oct*_*ccl 3

问题在于一对一关系的配置,因为一端必须是principal,而另一端必须是dependent。当你配置这种关系时,实体框架要求依赖的主键也是外键。所以,不要映射UsuarioId为FK,否则,EF要求FK也必须是PK(注释该属性)。另一个问题是 EF 不知道谁是你们关系中的主角。要指定谁是主体,请使用该Required属性。例如,如果您在 上添加此属性AreaTitular,则指定要创建User,则AreaTitular必须在保存更改后设置该属性,因此在这种情况下您的主体是 ,Area依赖项是User,但这是假设的情况,我不知道我不知道你的逻辑。查看此帖子以获取更多信息:

现在,可以将两端指定为可选,但其中之一必须是主要的。如果这是您的情况,我建议您注释数据注释属性并使用 Fluent Api 来配置关系,如下所示:

   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   {
        modelBuilder.Entity<User>()
            .HasRequired(a => a.Area)
            .WithMany(c => c.Usuarios)
            .HasForeignKey(a => a.AreaId);

        modelBuilder.Entity<Area>()
            .HasOptional(a => a.Usuario)
            .WithOptionalPrincipal(u => u.AreaTitular);
   }
Run Code Online (Sandbox Code Playgroud)

我建议您阅读此页面以更好地理解一对一关系。