设置
使用MVC 3 + Code First
以下是我的课程
public class Member
{
[Key]
public Guid ID { get; set; }
[Required]
public String Email { get; set; }
[Required]
public String FirstName { get; set; }
[Required]
public String LastName { get; set; }
public String Sex { get; set; }
public String Password { get; set; }
public String PasswordSalt { get; set; }
public DateTime RegisterDate { get; set; }
public DateTime LastOnline { get; set; }
public String SecurityQuestion { get; set; }
public String SecurityAnswer { get; set; }
public virtual ICollection<FamilyMember> Families { get; set; }
public virtual ICollection<Relationship> Relationships { get; set; }
}
public class Relationship
{
[Key]
public Guid ID { get; set; }
[ForeignKey("Member1")]
public Guid Member1ID { get; set; }
[ForeignKey("Member2")]
public Guid Member2ID { get; set; }
public Guid RelationshipTypeID { get; set; }
public virtual RelationshipType RelationshipType { get; set; }
public virtual Member Member1 { get; set; }
public virtual Member Member2 { get; set; }
}
以下是问题
正在使用以下列创建数据库表“Relationship”:
ID,Member1ID,Member2ID,RelationshipTypeID, Member_ID
为什么要创建 Member_ID 列?
我看过this帖子,其中用户具有相同类型的设置,但我不确定如何正确定义InverseProperty。我尝试使用流畅的API调用,但我可以告诉他们在这里不会工作,因为我有两个外键引用同一个表。
任何帮助将不胜感激!
答案 0 :(得分:2)
Member_ID
是EF为导航属性Member.Relationships
创建的外键列。它属于Member.Relationships
引用最终端点的第三个关联,该端点未在Relationship
实体中公开。这种关系与Relationship.Member1
和Relationship.Member2
中的其他两个关系无关,这两个关系也都有一个未在Member
中公开的端点。
我想,这不是你想要的。您需要始终在两个实体中对端点来创建关联。一个端点始终是导航属性。第二个端点 也可以是导航属性,但不是必需的,您可以省略第二个导航属性。
现在,不可能的是将两个导航属性(Member1
和Member2
)与一个一个导航属性关联在一个实体中(Relationships
)在另一个实体中。这就是你想要做的事情。
我认为您的Member.Relationships
属性应该表明该成员在关系中属于Member1
或Member2
,或者参与关系,无论如果是Member1
或Member2
。
很遗憾,你无法在模型中恰当地表达这一点。您必须引入类似RelationsshipsAsMember1
和RelationsshipsAsMember2
的内容,对于这两个集合,您可以使用InverseProperty
属性,如另一个问题所示。此外,您还可以添加一个辅助属性来连接两个集合。但这不是映射的属性,而是只读:
public class Member
{
// ...
[InverseProperty("Member1")]
public virtual ICollection<Relationship> RelationshipsAsMember1 { get; set; }
[InverseProperty("Member2")]
public virtual ICollection<Relationship> RelationshipsAsMember2 { get; set; }
public IEnumerable<Relationship> AllRelationships
{
get { return RelationshipsAsMember1.Concat(RelationshipsAsMember2); }
}
}
访问AllRelationships
将导致两次查询并往返数据库(使用延迟加载),以便在它们在内存中连接之前先加载这两个集合。
通过此映射,Member_ID
列将消失,您将只获得两个预期的外键列Member1ID
,Member2ID
,因为现在您只有两个关联而不是三个。< / p>
您还可以考虑是否需要Relationships
实体中的Member
集合。如上所述,双方的导航属性不是必需的。如果您很少需要从成员导航到其关系,您可以使用Relationship
集上的查询来获取关系,如下所示:
var relationships = context.Relationships
.Where(r => r.Member1ID == givenMemberID || r.Member2ID == givenMemberID)
.ToList();
...或...
var relationships = context.Relationships
.Where(r => r.Member1ID == givenMemberID)
.Concat(context.Relationships
.Where(r => r.Member2ID == givenMemberID)
.ToList();
这将为您提供ID = givenMemberID
的成员参与的所有关系,而无需Member
实体上的导航集合。