如何使用EF Core中的联接表映射具有“自分层”关系的实体

时间:2019-07-19 07:12:50

标签: entity-framework .net-core ef-core-2.0 ef-core-2.1 ef-core-2.2

我在使用现有数据库结构时遇到了麻烦,不幸的是我无法更改。

我有下表(为简化起见缩写)

CREATE TABLE EntityRelationship (
    ChildID int,
    ParentID int
)

CREATE TABLE Entity (
    EntityID varchar,
    EntityRelationshipID int
)

我按如下所示映射实体:

public class EntityRelationship {
    [ForeignKey("Entity")]
    public int ChildId { get; set; }
    [ForeignKey("ParentEntity")]
    public int ParentId { get; set; }

    public Entity ParentEntity { get; set; }
    public Entity Entity { get; set; }
}

public class Entity {
    [Key]
    public String EntityId { get; set; }

    [ForeignKey("ParentEntity")]
    public int EntityRelationshipId { get; set; }

    public EntityRelationship ParentEntity { get; set; }
}

modelBuilder.Entity<EntityRelationship>()
    .HasOne(c => c.ChildEntity)
    .WithOne(c => c.ParentEntity);

我确保在加载时渴望加载导航属性,但仍然没有得到任何结果。

我假设它与我的映射有关,或者可能是因为数据库结构和连接表不是按惯例具有一对一映射,而是使整个过程崩溃了。

>

有人能对此有所启发吗?

为了清楚起见,我想去做的是:

Entity parent = db.Entities.First().ParentEntity.Entity;

while (parent.ParentEntity.Entity != null) {
     parent = parent.ParentEntity.Entity;
}

以便找到实体的最高父级。

1 个答案:

答案 0 :(得分:2)

在此模型中,链接实体EntityRelationship暗示由ChildIdParentId表示的两个 FK关系。对于这两种关系,链接实体是依赖的,主要实体Entity主要,其中EntityRelationshipId主要密钥

因此,基本上,您需要正确映射这两个 关系的键和导航属性。删除[ForeignKey]数据注释以免混乱

public class Entity
{
    [Key]
    public string EntityId { get; set; }
    public int EntityRelationshipId { get; set; }
    public EntityRelationship ParentEntity { get; set; }
}

public class EntityRelationship
{
    public int ChildId { get; set; }
    public int ParentId { get; set; }
    public Entity ParentEntity { get; set; }
    public Entity Entity { get; set; }
}

,然后使用以下流畅的配置(可以从另一面进行配置,我选择了Entity,因为它对我来说更自然地看到了映射):

modelBuilder.Entity<Entity>(builder =>
{
    // child => parent
    builder.HasOne(e => e.ParentEntity)
        .WithOne(r => r.Entity)
        .HasForeignKey<EntityRelationship>(r => r.ChildId)
        .HasPrincipalKey<Entity>(e => e.EntityRelationshipId);
    // parent => children
    builder.HasMany<EntityRelationship>()
        .WithOne(r => r.ParentEntity)
        .HasForeignKey(r => r.ParentId)
        .HasPrincipalKey(e => e.EntityRelationshipId);
});