Fedoranimus
Fedoranimus

Reputation: 836

How to create multiple Many-to-Many relationships using the same join table [EF7/Core]

Is it possible to create 2 M:M relationships using the same join table?

I have the following situation and am receiving the exception:

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

In Tag:

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; }

In ApplicationUser:

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; }
}

In UserTag (CLR join):

public class UserTag
{
    public string UserId { get; set; }
    public ApplicationUser User { get; set; }

    public int TagId { get; set; }
    public Tag Tag { get; set; }
}

In 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);
    }

Do I need to create separate CLR classes? Something like UserStudyTag and UserExpertTag?

Thanks!

Upvotes: 0

Views: 588

Answers (1)

Dmitry
Dmitry

Reputation: 16825

Step down to SQL DB. You want to have table UserTag with one UserId field. How EF should guess, which records in this table are related to StudyTags and which to ExpertTags collections?

You should duplicate something.

Either split UserTag to two tables (UserStudyTag and UserExpertTag), or make two UserId fields in UserTag, say ExpertUserId and StudyUserId. Both nullable, with only one having some value in each record.

Upvotes: 1

Related Questions