【问题标题】:Entity Framework (Code First) One to Many and One to One relations (with two entities). How to?实体框架(代码优先)一对多和一对一关系(有两个实体)。如何?
【发布时间】:2015-04-09 17:50:33
【问题描述】:

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

有两个表:Users 和Areas。一个用户属于一个需要的区域,一个区域可以有零个或一个用户(作为管理员)。那么:

用户 *..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; }
}

区域类:

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; }
}

更新数据库命令的错误:

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

任何帮助将不胜感激:)

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

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

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

【问题讨论】:

  • Entity Framework 不知道哪一个是 1,哪一个是 0。它告诉你在错误中做什么。但是为什么你有两个Area 导航属性呢?
  • @Claies User.Area 转到 Area.Usuario,而 User.AreaTitular 转到 Area.Usuario.. 这是错的吗?
  • @ChrisV 我的问题是关于在两个类上有两个关系。另一个是关于 1..1 关系对吗?
  • 我仍然不确定我是否理解您想要做什么。您想对同一个类有 2 种不同的关系吗?

标签: entity-framework one-to-many code-first one-to-one relationships


【解决方案1】:

问题在于一对一关系的配置,因为一端必须是主体,而另一端必须是从属。当你在配置这种关系时,Entity Framework 要求依赖的主键也是外键。所以,不要将UsuarioId 映射为 FK,否则,EF 要求 FK 也必须是 PK(注释财产)。另一个问题是 EF 不知道谁是你们关系中的负责人。要指定谁是委托人,请使用Required 属性。例如,如果您在AreaTitular 上添加此属性,则指定要创建User,必须在保存更改后设置AreaTitular 属性,因此在这种情况下您的主体是Area 并且依赖是User,但这是假设的场景,我不知道你的逻辑。 查看此帖子了解更多信息:

现在,可以将两端指定为可选,但其中一个必须是主体。如果是这种情况,我建议您注释 Data Annotations 属性并使用 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);
   }

我建议您阅读此page 以更好地了解一对一关系。

【讨论】:

  • 谢谢!我正在阅读那本书和关于一对一关系的部分,我发现的问题是关于两个实体上的两个关系以及如何配置它们。最后,也许最好的方法是避免这种问题,并使用其他表来处理这种关系,你不觉得吗?
  • 使用流利的 api 解决方案,表格如下所示:Areas [AreaId(PK, int, not null), Name] Users [UserId(PK, int, not null), Name, AreaId(FK , int, not null), AreaTitular_AreaId(FK, int, null)] 我觉得这样就解决了问题!
  • 为你高兴,我的朋友 ;),第一个 FK 与一对多关系 (AreaId) 相关,第二个 (AreaTitular_AreaId) 与一对一相关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多