如何使用同一个连接表创建多个多对多关系 [EF7/Core]

Posted

技术标签:

【中文标题】如何使用同一个连接表创建多个多对多关系 [EF7/Core]【英文标题】:How to create multiple Many-to-Many relationships using the same join table [EF7/Core] 【发布时间】:2016-11-29 22:23:02 【问题描述】:

是否可以使用同一个连接表创建 2 M:M 关系?

我有以下情况并收到异常:

Unhandled Exception: System.InvalidOperationException: Cannot create a relationship between 'ApplicationUser.ExpertTags' and 'UserTag.User', because there already is a relationship between 'ApplicationUser.StudyTags' and 'UserTag.User'. Navigation properties can only participate in a single relationship

在标签中:

public class Tag 
    public Tag() 
        Users = new List<UserTag>();
    
    public int TagId  get; set; 
    public string Name  get; set; 
    public string Description  get; set; 

    public ICollection<UserTag> Users  get; set; 

在应用程序用户中:

public class ApplicationUser : IdentityUser

    public ApplicationUser()
    
        StudyTags = new HashSet<UserTag>();
        ExpertTags = new HashSet<UserTag>();
    

    public string FirstName  get; set; 
    public string LastName  get; set; 
    public string Location  get; set; 
    public ICollection<UserTag> StudyTags  get; set; 
    public ICollection<UserTag> ExpertTags  get; set; 

在 UserTag 中(CLR 加入):

public class UserTag

    public string UserId  get; set; 
    public ApplicationUser User  get; set; 

    public int TagId  get; set; 
    public Tag Tag  get; set; 

在 ApplicationDbContext 中:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<UserTag>()
            .HasKey(x => new  x.UserId, x.TagId );

        modelBuilder.Entity<UserTag>()
            .HasOne(ut => ut.User)
            .WithMany(u => u.StudyTags)
            .HasForeignKey(ut => ut.UserId);

        modelBuilder.Entity<UserTag>()
            .HasOne(ut => ut.User)
            .WithMany(u => u.ExpertTags)
            .HasForeignKey(ut => ut.UserId);

        modelBuilder.Entity<UserTag>()
            .HasOne(ut => ut.Tag)
            .WithMany(t => t.Users)
            .HasForeignKey(ut => ut.TagId);
    

我需要创建单独的 CLR 类吗? UserStudyTagUserExpertTag 之类的东西?

谢谢!

【问题讨论】:

【参考方案1】:

降级到 SQL DB。您希望表 UserTag 带有一个 UserId 字段。 EF 应该如何猜测,该表中哪些记录与StudyTags 相关,哪些与ExpertTags 集合相关?

你应该复制一些东西。

要么将UserTag 拆分为两个表(UserStudyTagUserExpertTag),要么在UserTag 中创建两个UserId 字段,例如ExpertUserIdStudyUserId。两者都可以为空,每条记录中只有一个具有某些值。

【讨论】:

谢谢。我最终使用了两个单独的表。

以上是关于如何使用同一个连接表创建多个多对多关系 [EF7/Core]的主要内容,如果未能解决你的问题,请参考以下文章

一对多还是多对多?

如何在Laravel中的多对多关系中添加“别名”?

多个多对多关系(循环关系)

Laravel 中多对多关系中连接表的命名约定

如何为连接表中的其他属性创建多对多 Hibernate 映射?

如何在不破坏范式的情况下为多对多关系构建连接表