Entity framework 实体框架-多对多,一个主框架

Entity framework 实体框架-多对多,一个主框架,entity-framework,entity-framework-core,Entity Framework,Entity Framework Core,我有一个频道域模型,如下所示: public class Channel { public string Id {get; set;} public List<ChannelUser> ChannelUsers {get; set;} } ChannelUser的主键是(ChannelId,UserId) 这些频道用户中的一个(并且只有一个)可以是频道的所有者。 从理论上讲,一个用户可以是多个频道的所有者(但显然,ChannelUser只能是与其关联的频道的所有者) 我

我有一个
频道
域模型,如下所示:

public class Channel
{
   public string Id {get; set;}
   public List<ChannelUser> ChannelUsers {get; set;}
}
ChannelUser的主键是(ChannelId,UserId)

这些频道用户中的一个(并且只有一个)可以是频道的所有者。 从理论上讲,一个用户可以是多个频道的所有者(但显然,ChannelUser只能是与其关联的频道的所有者)

我希望在数据库级别强制执行这一点,而不是在
ChannelUser
上设置“IsOwner”属性,并使用业务逻辑确保每个通道只设置一次标志。我还想强制要求ChannelOwner是ChannelUsers之一,因此不希望直接与
Channel>User
建立关系,而是将其保留为
Channel>ChannelUser

因此,我将
频道
类更新如下:

public class Channel
{
   public string Id {get; set;}
   public List<ChannelUser> {get; set;}
   public ChannelUser Owner {get; set;}
}
我理解,但我认为这是我们想要的。因为两个关系的ChannelUser.ChannelId应始终为相同的Channel.Id

请任何人建议我如何构建这种关系,或者一种替代方法,它仍然强制执行表之间的
多对多
一对一
关系


这不是理想的方法,但可以做到,请看一下ER图:

理想的方法是使用适当的实体映射,如:

用户类别:

public class User
{
   public string Id {get; set;}
   public virtual List<Channel> Channels {get; set;}
   // Other properties....
}
映射:

modelBuilder.Entity<User>()
            .HasMany<Channel>(user => user.channels)
            .WithMany(channel => channel.users)
            .Map(cu =>
                    {
                        cu.MapLeftKey("UserId");
                        cu.MapRightKey("ChannelId");
                        cu.ToTable("ChannelUser");
             });

    // configure one-to-many relationship for ownership
    modelBuilder.Entity<Channel>()
        .HasRequired<User>(c => c.User)
        .WithMany(u => u.ChannelId )
        .HasForeignKey<int>(c => c.UserId);
modelBuilder.Entity()
.HasMany(user=>user.channels)
.WithMany(channel=>channel.users)
.Map(cu=>
{
cu.MapLeftKey(“用户ID”);
cu.MapRightKey(“ChannelId”);
cu.ToTable(“信道用户”);
});
//为所有权配置一对多关系
modelBuilder.Entity()
.HasRequired(c=>c.User)
.WithMany(u=>u.ChannelId)
.HasForeignKey(c=>c.UserId);

规范化后,在控制器代码中检查用户是否存在的责任应该相当容易,或者我们可以使用DB过程、触发器创建约束,检查给定所有者ID是否确实在给定频道的ChannelUser表中。

用简单的英语语句思考。一个频道有多个用户。频道只有一个所有者。用户可以有多个频道,但可以是任何单个频道的所有者。因此,三个表Channel、User和ChannelUser之间的关系就像Channel和users之间的多对多关系,以及owner关系之间的1对1关系。在Channel类中,您将所有者引用为ChannelUser,而不是用户类,这有点像循环引用。另外,你应该有用户和频道的列表,而不是ChannelUser,因为它只是中间类,除非你有额外的元数据。谢谢你的评论。我更新了我的问题以澄清:一个用户可以是多个频道的所有者(但ChannelUser只能是一个频道的所有者,由ChannelId确定)。我确实有关于这种关系的额外元数据,我只是为了简洁起见才写了这篇文章。谢谢,我将创建relationship Channel>User来表达您建议的主要所有者。如果你想写一个答案,我会接受。深入研究,这是可能的,但你的数据结构可能需要改变一点以适应约束。
Both relationships between 'ChannelUser.Channel' and 'Channel.ChannelUsers' and between 'ChannelUser' and 'Channel.Owner' could use {'ChannelId'} as the foreign key. To resolve this configure the foreign key properties explicitly on at least one of the relationships.
public class User
{
   public string Id {get; set;}
   public virtual List<Channel> Channels {get; set;}
   // Other properties....
}
public class Channel
{
   public string Id {get; set;}
   public List<User> Users {get; set;}
   public User Owner {get; set;}
   public string? OwnerId { get; set; }
   public User Owner { get; set; }
}
public class ChannelUser
{
   public string Id {get; set;}
   public string ChannelId {get; set;}
   public string UserId {get; set;}
}
modelBuilder.Entity<User>()
            .HasMany<Channel>(user => user.channels)
            .WithMany(channel => channel.users)
            .Map(cu =>
                    {
                        cu.MapLeftKey("UserId");
                        cu.MapRightKey("ChannelId");
                        cu.ToTable("ChannelUser");
             });

    // configure one-to-many relationship for ownership
    modelBuilder.Entity<Channel>()
        .HasRequired<User>(c => c.User)
        .WithMany(u => u.ChannelId )
        .HasForeignKey<int>(c => c.UserId);