EF建立自我关系

时间:2012-03-18 15:49:08

标签: entity-framework

这次我有一个简单的问题:

我有一张与自己有关的表

=====================
| Id                |  
| IdParent          |
| NodeName          | 
=====================

IdParent 可以有0个或多个 Id 。 问题是,如何使用FluentApi或数据anotations配置此关系。

这种关系的结果是一棵树(有两个级别),如下所示:

a
|---b
|---c 
d
e
f---g    

其中(a,d,e,f)是父节点,(b,c,g)是子节点。

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

实体框架支持自引用外键。目前尚不清楚您是数据库优先还是代码优先。

如果您是数据库第一人,只需在数据库中创建自引用外键,即可从数据库更新模型。 EF至少支持EF 4。

支持这种键

从代码第一的角度来看,它可能有点棘手。如果您使用的是EF 4.x,则需要覆盖OnModelCreating函数(请参阅example here)。如果您使用的是EF 5(来自.net 4.5 beta或2011年6月的CTP),那么this question会提供一些很好的指导。缺点是在您的模型上使用[ForeignKey("IdParent")]属性。

无论哪种方式,您都应该看到类似XML的内容......

  <edmx:Runtime>
    <edmx:StorageModels>
    <Schema Namespace="...">
          <AssociationSet Name="FK_Culture_has_ParentCulture" 
                   Association="AL_Model.Store.FK_Culture_has_ParentCulture">
            <End Role="Culture" EntitySet="Culture" />
            <End Role="Culture1" EntitySet="Culture" />
          </AssociationSet>

 .....
 .....
 <edmx:ConceptualModels>
    <Schema Namespace="...">
    <EntityContainer Name="..." >
      <Association Name="FK_Culture_has_ParentCulture">
        <End Role="Culture" Type="AL_Model.Store.Culture" Multiplicity="0..1" />
        <End Role="Culture1" Type="AL_Model.Store.Culture" Multiplicity="*" />
          <ReferentialConstraint>
            <Principal Role="Culture">
              <PropertyRef Name="CultureID" />
            </Principal>
            <Dependent Role="Culture1">
              <PropertyRef Name="ParentCultureID" />
            </Dependent>
          </ReferentialConstraint>
      </Association>

自我参考结构

这句话引起了一些注意:

Where IdParent Could Have 0 or many Id. 

为了拥有“零或父ID”,您需要在表中包含一个包含零作为ID的条目。为什么?因为外键需要链接到某些东西。但是,我怀疑你想要的是使IdParent可以为空的。您的问题未指定数据库,但大多数主要数据库仅在存在值时才强制执行外键。换句话说,IdParent中的Null表示没有父母。

答案 1 :(得分:1)

经过多次尝试...最佳解决方案是从为此提供EBarr示例的第一个链接中提取的。

我的最后一个解决方案是:

将Icollection添加到我的表格中:

public partial class myTable
{
    public myTable()
    {
        this.Ids= new HashSet< myTable >();
    }
    public decimal id {get;set;}
    public decimal idParent {get;set;}
    public string  NodeName {get;set;}

    public Icollection<myTable> Ids {get;set;}
}

然后使用Fluent Api

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<myTable>()
        .HasMany(x => x.Ids)
        .WithOptional()
        .HasForeignKey(m => m.IdParent);
}