如何使用实体框架正确建模自引用多父关系

时间:2015-04-16 16:08:36

标签: c# entity-framework entity-framework-6

我正在尝试在EF6中为以下自引用人员类建模。

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }

    public int? MotherId { get; set; }
    public Person Mother { get; set; }

    public int? FatherId { get; set; }
    public Person Father { get; set; }

    public virtual ICollection<Person> Children { get; set; }
}

我的DbContext看起来像这样:

public virtual DbSet<Person> People { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasOptional(m => m.Mother)
        .WithMany(c => c.Children)
        .HasForeignKey(m => m.MotherId);

     modelBuilder.Entity<Person>()
        .HasOptional(f => f.Father)
        .WithMany(c => c.Children)
        .HasForeignKey(f => f.FatherId);
}

尝试使用以下代码将人员添加到数据库时:

db.People.Add(new Person { Name = "Jane Doe" });

我收到此错误:

  

未处理的类型&#39; System.InvalidOperationException&#39;   发生在EntityFramework.dll

中      

附加信息:序列不包含匹配元素

这个错误意味着什么,我该如何纠正?可选地,有没有更好的方法来建模这个对象(例如:使用母语的子类:人和父:人)? / p>

2 个答案:

答案 0 :(得分:1)

我提出了以下解决方案,它可以生成一个干净的数据库,并在添加关系时提供更大的灵活性:

public interface IParent
{
    ICollection<Person> Children { get; set; }
}

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }

    public int? MotherId { get; set; }
    public Female Mother { get; set; }

    public int? FatherId { get; set; }
    public Male Father { get; set; }
}

public class Male : Person, IParent
{
    public virtual ICollection<Person> Children { get; set; }
}

public class Female : Person, IParent
{
    public virtual ICollection<Person> Children { get; set; }
}

DbContext仅包含:

public virtual DbSet<Person> People { get; set; }
public virtual DbSet<Female> Females { get; set; }
public virtual DbSet<Male> Males { get; set; }

结果数据库如下所示:

ID  Name    MotherId    FatherId    Discriminator
1   Jane    NULL        NULL        Female
2   John    NULL        NULL        Male
3   Jimmy   1           2           Male
4   Jenn    1           2           Female

此解决方案还提供了以多种方式添加关系的灵活性:

mom.Children.Add(son); // or
son.Mother = mom;

答案 1 :(得分:0)

我会做以下事情。虽然它可能不符合您的“实体框架”要求

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }

    public int? MotherId { get; set; }
    public int? FatherId { get; set; }
}

public Class RelationFinder
{
    Public Person GetMother(IEnumerable<Person> people, Person child)
    {
        return people.FirstOrDefault(p=>p.Id = child.MotherId);
    }

    Public Person GetFather(...

    Public IEnumerable GetChildern(...
}