将父级和子级关系集映射到EF6中的单个表

时间:2013-11-21 14:07:38

标签: c# sql entity-framework

我正在使用EF6代码优先尝试映射到所需的架构

要求是拥有组织表。每个组织可以有零到多个父母,零到多个孩子

拥有一个包含父子关系的单一关系表

所以我希望有这样的POCO:

public class Organisation
{
    public Organisation()
    {
        Children = new Collection<Organisation>();
        Parents = new Collection<Organisation>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Organisation> Parents { get; set; }
    public virtual ICollection<Organisation> Children { get; set; }
}

和这样的映射:

public class OrganisationMap : EntityTypeConfiguration<Organisation>
{
    public OrganisationMap()
    {
        HasMany(n => n.Children)
            .WithMany()
            .Map(m => m.ToTable("OrganisationRelationship").MapLeftKey("ParentId").MapRightKey("ChildId"));
        HasMany(n => n.Parents)
            .WithMany()
            .Map(m => m.ToTable("OrganisationRelationship").MapLeftKey("ChildId").MapRightKey("ParentId"));

    }
}

但如果我在设置之后尝试添加迁移,则会收到错误消息:

  

OrganisationOrganisation1:名称:EntitySet   'OrganisationOrganisation1'与架构'dbo'和表格   “组织关系”已经定义。每个EntitySet必须   引用一个唯一的模式和表。

有没有办法实现这个目标?


有关其他信息。我持有父关系的原因是,在加载数据时,我需要找到所有没有父节点的节点,并将它们视为根集合。

如果有更好的方法来做这件事,而不是举行父母收藏,我会非常高兴!

如果我只使用子集合添加迁移,那么所有工作


感谢您的投入。我仍然试图找出是否有可能有一个或多个已知的根来简化构建图形,但我感兴趣的是这种映射是否可行......


数据排序如下: a directed acyclic graph

2 个答案:

答案 0 :(得分:2)

您正在定义映射两次 - 只尝试一次,类似于下面的

public OrganisationMap()
{
    HasMany(n => n.Children)
        .WithMany( n => n.Parents )
        .Map(m =>
            m.ToTable("OrganisationRelationship")
            .MapLeftKey("ParentId")
            .MapRightKey("ChildId"));
}

答案 1 :(得分:1)

在同一级别上显示具有多个父项的项目是很困难的。

由于您在问题中提到了 root 这个词,我认为理想模型会有一个父项和多个子项,现在项目的父项可以有父项,这样创建层次结构。您可以为根级别元素实现可选父级的概念。

如果你想为单个项目实现多个父母的想法,请关注@Moho回答 如果您想要层次结构,请尝试以下操作:

public class Organisation
{
    public Organisation()
    {
        Children = new Collection<Organisation>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Organisation Parent { get; set; }
    public virtual ICollection<Organisation> Children { get; set; }

    public IEnumerable<Organisation> Ancestors
    {
        get
        {
            var item = this;
            while (item.Parent != null)
            {
                yield return item.Parent;
                item = item.Parent;
            }
        }
    }
}

和你的地图:


public class OrganisationMap : EntityTypeConfiguration<Organisation>
{
    public OrganisationMap()
    {
        HasOptional(n => n.Parent)
            .WithMany(n => n.Children)
            .Map(m => m.MapKey("ParentId"));

        Ignore(n => n.Ancestors);
    }
}

<强>更新
通过调用Include,您可以通过一次拉动从DB中加载所有父项。这会为每个被拉动的项目加载父级。

db.Organisations.Include(x => x.Parent).Include(x => x.Children).Where(...your condition)