首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架-多对多,一主

问实体框架-多对多,一主
EN

Stack Overflow用户
提问于 2021-04-21 15:52:01
回答 1查看 20关注 0票数 0

我有一个Channel域模型:

代码语言:javascript
复制
public class Channel
{
   public string Id {get; set;}
   public List<ChannelUser> ChannelUsers {get; set;}
}

和一个ChannelUser类,如下所示(我在表中有额外的元数据,为了简洁,在这里删除了它,这就是为什么我使用一个特定的类来表示多对多关系)。

代码语言:javascript
复制
public class ChannelUser
{
   public string ChannelId {get; set;}
   public string UserId {get; set;}
}

ChannelUser的主键是(ChannelId,UserId)。

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

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

因此我更新了Channel类,如下所示:

代码语言:javascript
复制
public class Channel
{
   public string Id {get; set;}
   public List<ChannelUser> {get; set;}
   public ChannelUser Owner {get; set;}
}

并添加了以下流畅的API表达式:

代码语言:javascript
复制
            modelBuilder.Entity<ChannelUser>().HasKey(cu => new { cu.ChannelId, cu.UserId });

            modelBuilder.Entity<ChannelUser>().HasOne<Channel>(x => x.Channel).WithMany(x => x.ChannelUsers)
                .OnDelete(DeleteBehavior.NoAction);

            modelBuilder.Entity<ChannelUser>().HasOne<User>(x => x.User).WithMany(x => x.UserChannels)
                .OnDelete(DeleteBehavior.NoAction);

添加迁移时,这会导致:

代码语言:javascript
复制
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.

我理解这一点,但我认为这是我们所希望的。因为对于两个关系,ChannelUser.ChannelId应该始终是相同的Channel.Id。

有没有人能建议我如何构建这种关系,或者是一种替代方法,仍然可以在表之间强制执行many to many和one to one关系?

​

​

EN

回答 1

Stack Overflow用户

发布于 2021-04-21 17:23:34

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

​

理想的方法是拥有适当的实体映射,如下所示:

用户类:

代码语言:javascript
复制
public class User
{
   public string Id {get; set;}
   public virtual List<Channel> Channels {get; set;}
   // Other properties....
}

通道类:

代码语言:javascript
复制
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; }
}

要加入这两个类的ChannelUser类:

代码语言:javascript
复制
public class ChannelUser
{
   public string Id {get; set;}
   public string ChannelId {get; set;}
   public string UserId {get; set;}
}

映射:

代码语言:javascript
复制
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);

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67191506

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档