【问题标题】:EF 4.1 Code First Relationship tableEF 4.1 代码优先关系表
【发布时间】:2011-11-06 07:21:09
【问题描述】:

设置

使用 MVC 3 + 代码优先

这是我的课程

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; }

    }

问题来了

正在使用以下列创建数据库表“关系”:

ID、Member1ID、Member2ID、RelationshipTypeID、Member_ID

为什么要创建 Member_ID 列?

我看到this 帖子中用户具有相同类型的设置,但我不确定如何正确定义 InverseProperty。我尝试使用流利的 API 调用,但据我所知,它们在这里不起作用,因为我有两个外键引用同一个表。

任何帮助将不胜感激!

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework ef-code-first


    【解决方案1】:

    Member_ID 是 EF 为导航属性 Member.Relationships 创建的外键列。它属于来自Member.Relationships 的第三个关联,指的是未在您的Relationship 实体中公开的端点。此关系与Relationship.Member1Relationship.Member2 中的其他两个关系无关,这两个关系也都具有未在Member 中公开的端点。

    我猜,这不是你想要的。您需要在两个实体中始终有 个端点来创建关联。一个端点始终是导航属性。第二个端点也可以是导航属性,但不是必须的,你可以省略第二个导航属性。

    现在,不可能将两个导航属性(Member1Member2)与一个导航属性(Relationships)关联到一个实体中) 在另一个实体中。这显然是你想要做的。

    我假设您的 Member.Relationships 属性应该表示该成员在关系中是 Member1Member2,或者它参与关系,否问题 如果是Member1Member2

    很遗憾,您无法在模型中恰当地表达这一点。您必须引入RelationsshipsAsMember1RelationsshipsAsMember2 之类的内容,对于这两个集合,您可以使用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 列将消失,您将只获得两个预期的外键列 Member1IDMember2ID,因为现在您只有两个关联,而不再是三个。

    您还可以考虑是否需要Member 实体中的Relationships 集合。如前所述,不需要两侧的导航属性。如果您很少需要从一个成员导航到它的关系,您也可以使用 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 实体上的导航集合。

    【讨论】:

    • 你让我想得更多,我认为你甚至不需要 Member.Relationships 属性是对的。我猜从我过去的作品中,你总是有办法导航。但是如果我需要加载关系,我可以只查询关系表。这样做的一个缺点是它在我的视图模型中不容易使用。
    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多