考虑这种情况:
public class House
{
public string Name { get; set; }
public virtual Person Person1 { get; set; }
public virtual Person Person2 { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public House House { get; set; }
}
// Relationships
this.HasOptional(t => t.Person1)
.WithRequired(t => t.House);
this.HasOptional(t => t.Person2)
.WithRequired(t => t.House);
当我尝试插入House的实例时,抛出了一个MetaDataException:
指定的架构无效。错误:(36,6):错误0040:输入 House_Person1未在命名空间Company.Models(Alias = Self)中定义。
经过多次黑客攻击后,我认为这样做有效:
// Relationships
this.HasOptional(t => t.Person1)
.WithRequired();
this.HasOptional(t => t.Person2)
.WithRequired();
但是我不会让EF填充Person.House属性。我可以模仿这种行为(如下所示)吗?
public virtual Person Person1
{
get
{
return _person1;
}
set
{
_person1 = value;
_person1.Haushalt = this;
}
}
public virtual Person Person2
{
get
{
return _person2;
}
set
{
_person2 = value;
_person2.Haushalt = this;
}
}
答案 0 :(得分:2)
您不能在两个不同的关系中使用相同的导航属性(Person.House
)(House_Person1
和House_Person2
)。
另一个限制是EF仅支持shared primary key associations作为真正的一对一关系。这意味着相关的House
和Person
必须具有相同的主键值。但由此得出House.Person1
和House.Person2
需要与House
具有相同的PK值。换句话说:Person1
和Person2
永远不会是不同的人。
我建议您将关系映射为一对多关系,并在应用程序的业务逻辑中确保House
不得超过两个Person
。 (因为您当前的映射允许Person1
和Person2
是可选的,所以允许零个或仅一个人:
public class House
{
public string Name { get; set; }
public virtual ICollection<Person> People { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public House House { get; set; }
}
this.HasMany(t => t.People)
.WithRequired(t => t.House);
修改强>
如果你想在Person
中保留两个House
导航属性,你只能将其映射为两个一对多的关系(即使这种关系在商业角度来看是错误的)而没有Person
中的导航属性(如显示here):
this.HasOptional(t => t.Person1)
.WithMany();
this.HasOptional(t => t.Person2)
.WithMany();
您可以像在上一段代码段中一样使用House
中的Person
媒体资源,但需要将其从模型中排除:
modelBuilder.Entity<Person>()
.Ignore(t => t.House);
当您从数据库加载Person.House
实体时, Person
不再是导航属性,无法加载它(使用急切或延迟加载)。