如何使用 entity framework 正确建模自引用多父关系
How to correctly model self-referencing multi-parent relationship using entity framework
我正在尝试在 EF6 中为以下自引用人建模 class。
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" });
我收到这个错误:
An unhandled exception of type 'System.InvalidOperationException'
occurred in EntityFramework.dll
Additional information: Sequence contains no matching element
这个错误是什么意思,我该如何更正它? 或者,是否有更好的方法来建模这个对象(例如:使用 subclass Mother:Person 和 Father:Person)?
我会做以下事情。尽管它可能不符合您的 'In Entity Framework' 要求
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(...
}
我提出了以下解决方案,可以生成干净的数据库并在添加关系时提供更大的灵活性:
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;
我正在尝试在 EF6 中为以下自引用人建模 class。
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" });
我收到这个错误:
An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll
Additional information: Sequence contains no matching element
这个错误是什么意思,我该如何更正它? 或者,是否有更好的方法来建模这个对象(例如:使用 subclass Mother:Person 和 Father:Person)?
我会做以下事情。尽管它可能不符合您的 'In Entity Framework' 要求
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(...
}
我提出了以下解决方案,可以生成干净的数据库并在添加关系时提供更大的灵活性:
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;