自引用多对多递归关系代码的第一个实体框架

时间:2011-02-26 04:24:27

标签: c# entity-framework many-to-many code-first

我似乎无法完成这项工作

class Member
{
    public virtual IList<Member> Friends { get; set; }
    [Key]
    public int MemberId { get; set; }
    public string Name{ get; set; }
}

我尝试添加Mappings但是徒劳无功。有没有办法用CTP5这样做?

5 个答案:

答案 0 :(得分:61)

按照惯例,Code First将单向关联作为一对多关联。因此,您需要使用流畅的API让Code First知道您希望拥有多对多的自引用关联:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>().HasMany(m => m.Friends).WithMany();
}

注意:CTP5中存在一个已知错误,它不允许您在此方案中自定义连接表列名称。

答案 1 :(得分:18)

如果我是正确的,您可以使用以下代码影响多对多的表名:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>().HasMany(m => m.Friends).WithMany().Map(m =>
        {
            m.MapLeftKey("MemberId");
            m.MapRightKey("FriendId");
            m.ToTable("MembersFriends");
        }
    );
}

希望这会有所帮助。

答案 2 :(得分:2)

你可以使用Model-First在EF 4 CTP5中使用它,但是CTP5 Code First有太多的错误,有自引用和多态查询配置,因此在这种情况下使用Code First。 Morteza Manavi(见其他答案)在他的博客上记录了其中几个。

答案 3 :(得分:2)

我希望无需编写流畅的API代码即可完成此任务。这是我的看法。

以下示例尝试保存用户访问过的其他用户个人资料以及访问该用户个人资料的人。遗憾的是,下面的示例不支持访问者和被访问用户的两个ID之外的其他属性。

导航属性已使用InversePropertyAttribute进行了链接。
entityframework.netentityframeworktutorial.net

中了解更多信息

型号↴

public class User
{   
    [InverseProperty(nameof(User.VisitingUsers))]
    public virtual List<User> VisitedUsers { get; set; }
    [NotMapped]
    public long? VisitedUsersCount { get { return this.VisitedUsers == null ? 0 : this.VisitedUsers.Count(); } }

    [InverseProperty(nameof(User.VisitedUsers))]
    public virtual List<User> VisitingUsers { get; set; }
    [NotMapped]
    public long? VisitingUsersCount { get { return this.VisitingUsers == null ? 0 : this.VisitingUsers.Count(); } }
}

生成的迁移代码↴

CreateTable(
    "dbo.UserUsers",
    c => new
    {
        User_Id = c.Long(nullable: false),
        User_Id1 = c.Long(nullable: false),
    })
    .PrimaryKey(t => new { t.User_Id, t.User_Id1 })
    .ForeignKey("dbo.Users", t => t.User_Id)
    .ForeignKey("dbo.Users", t => t.User_Id1)
    .Index(t => t.User_Id)
    .Index(t => t.User_Id1);

答案 4 :(得分:0)

你的例子不是多对多的关系,而是更多的递归关系。

我不确定如何修复它。但是你的代码的问题是你将在同一行上获得两个具有相同名称的字段。 MemberId表示行的id,MemberId表示朋友的id。

修改

尝试这样做:

    class Member 
    { 
        [Key]
        public int MemberId { get; set; } 
        public string Name { get; set; }

        public virtual IList<FriendRelationship> Friends { get; set; } 

    }

    class FriendRelationship
    {
        [Key]
        public int RelationshipId { get; set; }

        public Member Friend { get; set; }
    }