C# 自引用多对多递归关系代码优先实体框架

C# 自引用多对多递归关系代码优先实体框架,c#,entity-framework,many-to-many,code-first,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; } } 类成员 { 公共虚拟IList好友{get;set;} [关键] public int MemberId{get;set;} 公共字符串名称{get;se

我似乎一点也做不到

class Member
{
    public virtual IList<Member> Friends { get; set; }
    [Key]
    public int MemberId { get; set; }
    public string Name{ get; set; }
}
类成员
{
公共虚拟IList好友{get;set;}
[关键]
public int MemberId{get;set;}
公共字符串名称{get;set;}
}

我尝试添加映射,但没有成功。使用CTP5有什么方法可以做到这一点吗?

您的示例不是多对多关系,而是一种递归关系

我不知道如何修理它。但是,代码的问题是,您将在同一行中获得两个同名字段。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; }
    }
类成员
{ 
[关键]
public int MemberId{get;set;}
公共字符串名称{get;set;}
公共虚拟IList好友{get;set;}
}
班级友谊
{
[关键]
public int RelationshipId{get;set;}
公共成员友元{get;set;}
}

按照惯例,code First将单向关联视为一对多。因此,您需要使用fluent API让代码首先知道您希望有多对多自引用关联:

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");
        }
    );
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasMany(m=>m.Friends).WithMany().Map(m=>
{
m、 MapLeftKey(“成员ID”);
m、 MapRightKey(“FriendId”);
m、 ToTable(“会员朋友”);
}
);
}

您可以使用Model First在EF 4 CTP5中实现这一点,但CTP5 code First具有太多的自引用和多态查询配置错误,无法在此类场景中使用code First。Morteza Manavi(见其他答案)在他的博客上记录了其中的几个表名。

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

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");
        }
    );
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasMany(m=>m.Friends).WithMany().Map(m=>
{
m、 MapLeftKey(“成员ID”);
m、 MapRightKey(“FriendId”);
m、 ToTable(“会员朋友”);
}
);
}

希望这能有所帮助。

我想在不必编写流畅的API代码的情况下完成这项工作。这是我的看法。

下面的示例尝试保存用户访问的其他用户配置文件以及访问该用户配置文件的用户。遗憾的是,以下示例不支持访问用户和被访问用户的两个ID以外的其他属性。

导航属性已使用链接。
在和中查看更多有关它的信息

模型↴
我不认为这首先与代码有关,但请检查。对我来说,这可能是多对多,因为可以通过引入一个带有[LeftMemberId]和[RightMemberId]的表[Friends]来解决。无论命名是否正确,我都无法实现这一点:(Thanx mate,我没有得到任何更改来尝试您的解决方案,但这是我手动执行此操作的初始解决方案。迫不及待地等待RTM:)Morteza,我一直在这里和您的博客上关注您。这工作完美无瑕!虽然生成的表名为[MemberMembers],这很奇怪,但这将在RTM中修复。谢谢你,伙计!您好,我需要知道如何使用多个自引用。例如,在相同的示例代码上;公共虚拟IList朋友{get;set;}公共虚拟IList父母{get;set;}这非常有效,谢谢。您知道有哪个was指定它将创建的多对多表的名称吗?MemberMembers这个东西工作正常,但看起来很难看。@Morteza当我添加HasMany时,我没有与Many链接的选项,我如何在EF core Latest中做到这一点呢。希望RTM能满足我们的要求。代码优先真是太棒了!只要有两个用户集合,这甚至可以在没有InverseProperty属性的情况下工作。EF将自动假定它们是对应的。
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);