当我需要具有相同类型的多个关系时,实体框架问题

时间:2016-11-02 00:56:35

标签: c# sql entity-framework

这个问题困扰了我一段时间,并希望得到任何帮助

假设我有两个类,用户和房间,基本上都是这样的

public class User
{
    [Key]
    public int UserId {get; set;}
    public string Username {get; set;}
    public virtual List<Room> Rooms {get; set;}
}

public class Room
{
    [Key]
    public int RoomId {get; set;}
    [ForeignKey("Owner")] // have tried with and without the explicit relationship
    public int OwnerId {get; set;}
    public User Owner {get; set; }
    public virtual List<User> Members {get; set;}
}

我希望建立一个结构,允许用户拥有多个房间,他们是所有者,但也可以作为成员包含在多个房间内。

问题来自于我实际上试图建立一个房间并添加成员。添加了所有者属性,但成员列表始终为空。

我正在使用注释API,但也尝试过流畅的API

当我尝试这个时,我得到一个多重性错误

 modelBuilder.Entity<Room>()
                .HasMany(t => t.Members).WithMany(u => u.Rooms);

我确信答案很简单,我对实体并不是那么好。任何帮助将不胜感激。

由于

2 个答案:

答案 0 :(得分:4)

UserRoom之间有两种关系:

  • 用户为所有者的房间(one-to-many
  • 用户所属的会员(many-to-many

单个Rooms集合不能代表两个关系,您需要两个集合:

public class User
{
    [Key]
    public int UserId {get; set;}
    public string Username {get; set;}
    public virtual List<Room> OwnerOfRooms {get; set;}
    public virtual List<Room> MemberOfRooms {get; set;}
}

并使用以下Fluent配置:

modelBuilder.Entity<User>()
    .HasMany(u => u.OwnerOfRooms)
    .WithRequired(r => r.Owner)
    .HasForeignKey(r => r.OwnerId);

modelBuilder.Entity<User>()
    .HasMany(u => u.MemberOfRooms)
    .WithMany(r => r.Members);

请注意,第二个关系将创建自动联结表UserRooms

答案 1 :(得分:1)

如果您正在使用EF Core,要创建多对多,这是您之后的事情,您需要拥有另一个实体UserRoom,其中包含1使用Users和1对多Room的多人,例如:

public class UserRoom
{
    public int UserId { get; set; }
    public User User { get; set; }
    public int RoomId { get; set; }
    public Room Room { get; set; }    
}

然后在User

    [InverseProperty(nameof(UserRoom.User))]
    public ICollection<UserRoom> UserRooms { get; set; }

,同样在Room

    [InverseProperty(nameof(UserRoom.Room))]
    public ICollection<UserRoom> UserRooms { get; set; }

在你的情况下,听起来你想要两个多对多的关系 - 一个用于房间会员,一个用于房间所有权。在这种情况下,您需要两次实现此模式,链接实体可能更适合命名为OwnerRoom和MemberRoom。

如果房间所有权对于单个用户是唯一的,那么您将需要MemberRoom和上面的模式以及与房间和用户的标准的1对多关系,就像您已经实施的那样,使用以下内容装饰User.Rooms

[InverseProperty(nameof(Room.Owner))]