dotnetdevcsharp
dotnetdevcsharp

Reputation: 3980

Many to many relationships EF Core 5.0.3

I need to replicate discords users model for my own site and the rules are.

A User can be part of multiple clubs Each user within those clubs can have the roles of admin or mod.

So Far I have site wide roles working but not within the club entity and I am having trouble linking up my clubs to the users

This is what I have so far I am using ef core 5.0.3 if that makes a difference.

ApplicaitonUser Model

public class ApplicationUser : IdentityUser
{
    public enum UserTypeEnum
    {
        Guest=0,
        User=1,
        Author=2,
        AddonOwner=3,
        GroupOwner=5,
        ClubMember=6,
        ClubAdmin=7,
        SuperAdmin=199,
        BandUser=999
    }
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public string? GamerTag { get; set; }
    public bool? isOnline { get; set; }
    public int? UserType { get; set; }
    public Guid? TennantId { get; set; }
    public Guid? ClubId { get; set; }

    public List<Badges>? Badges { get; set; }

    public List<Club>? Clubs { get; set; }

}

Then In my clubs I have

public  class Club
{

    public int Id { get; set; }
    public Guid? TeannatId { get; set; }
    public Guid? ClubId { get; set; }
    public Guid? UserId { get; set; }
    public string? Name { get; set; }       
    public string? Description { get; set; }
    public string? Url { get; set; }
    public int? ClubLikes { get; set; }
    public int? ClubDislikes { get; set; }
    public int? MembersCount { get; set; }
    public string? Logo { get; set; }
    public List<Flight>? Flights { get; set; }
    public string? ThumbNail { get; set; }
    public DateTimeOffset? GpdrRemoveRequestDate { get; set; }
    public bool? isGpdrRemoveRequest { get; set; }
    public DateTimeOffset? BannedTime { get; set; }
    public TimeSpan? BanPeriod { get; set; }
    public bool? isBanned { get; set; }
    public bool? isActive { get; set; }
    public bool? isDeleted { get; set; }
    public DateTime? CreatedDate { get; set; }
    public string? CreatedBy { get; set; }
    public  List<ApplicationUser>? Members { get; set; }
}

I tried this so far

 protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Club>().Property(x => x.ClubId).HasDefaultValueSql("NEWID()");
        modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole { Name = "Admin", NormalizedName = "Admin".ToUpper() });
        modelBuilder.Entity<ApplicationUser>()
            .HasOne<Club>()
            .WithMany(m => m.Members)
            .HasForeignKey(a => a.ClubId)
            .HasPrincipalKey(c => c.ClubId);
    }

But it only gives me a admin user and not roles within clubs also. The mapping for club only allows for one club per members when they could be part of multiple clubs its the exact same principle for discord where a channel would be a club and a user could be a mod or a normal user.

Then in my view I am returning.

 var club = await _context.Clubs.Include(c =>c.Members).ToListAsync();
 return View(club);

Where I would expect to see the many members per club but each member in term could belong to a different club multple times

Edit 2 still issues

I am still getting a zero count on my club users from the below person answer is their something else i must configure

enter image description here

Upvotes: 0

Views: 166

Answers (1)

Qudus
Qudus

Reputation: 1520

You need a table for an association between club and user to allow a user belong to multiple clubs. It is under that table you define the role of the user for that particular club.

public class ClubMember
{ 
    public string UserId {get;set;} 
    public int ClubId {get; set;} 
    public ApplicationUser User {get; set;} 
    public Club Club {get; set;} 
    public string RoleId {get;set;} 
    public IdentityRole Role {get; set;} 
} 

Remove List<Club> Clubs {get; set;} from ApplicationUser and also remove List<ApplicationUser> Members {get;set;} from Club

Then you can add the following properties to ApplicationUser and Club

public class ApplicationUser : IdentityUser
{
   public virtual List<ClubMember> ClubMembers{get;set;} 
} 
public class Club
{
   public virtual List<ClubMember> ClubMembers{get;set;} 
}

Update

To assign a club to a user, it's important you do;

var clubmember = new ClubMember {UserId = userId, ClubId = clubId, RoleId = roleId};
_context.ClubMembers.Add(clubmember);
await _context.SaveChangesAsync();

To query all members in a club with Id = 7 for example, you could do this;

var membersInClub = _context.ClubMembers.Include(c => c.User).Where(c => c.ClubId == 7).Select(c => c.User);

To query all clubs and their members

var clubs = _conext.Clubs.Include(c.ClubMembers);

Upvotes: 2

Related Questions