Search code examples
c#asp.net-mvcentity-frameworkasp.net-identitymany-to-many

ASP.NET MVC How to Use Many to Many Relationship Between ApplicationUser and Other Domain Class


I am currently working on a project using ASP.NET MVC, using Entity Framework and the code-first approach. Precursor, I am pretty new to all of these so some things still don't make a whole lot of sense to me.

I have made a many-to-many relationship between the ApplicationUser class and the Project class as such:

IdentityModels.cs:

public class ApplicationUser : IdentityUser
{
    public ICollection<UserProject> UserProjects { get; set; }
}

Project.cs:

public class Project
{
    [...]
    public ICollection<UserProject> UserProjects { get; set; }
}

UserProject.cs:

public class UserProject
{
    [Key, Column(Order = 1)]
    public string UserId { get; set; }
    [Key, Column(Order = 2)]
    public int ProjectId { get; set; }
    public ApplicationUser User { get; set; }
    public Project Project { get; set; }
}

I created a DbSet of UserProject to my ApplicationDbContext and created a migration for this.

With this being said, my question is how would I go about using this relationship? More specifically, if I wanted to display only the projects that the signed in user is assigned to, how could I go about doing that?

Also, my current assumption is that if I wanted to assign projects to users, I would ultimately just need to make a new UserProject object with the given User ID and the Project IDs I want to assign them with. Would that be how it would work?

Is my configuration of this relationship set up in a good way or should I consider changing it to get the above functionality?

Any and all help is appreciated. Thanks!


Solution

  • Starting from the last question, about the configuration

    EF6 supports many-to-many relations so there's no need to manually create the joining table UserProject You can simply do this

    IdentityModels.cs:

    public class ApplicationUser : IdentityUser
    {
        public ICollection<Project> Projects { get; set; }
    }
    

    Project.cs:

    public class Project
    {
        [...]
        public ICollection<ApplicationUser> Users { get; set; }
    }
    

    And that's it.

    Manually adding the joining table can still work, but you will then have to manage the CRUD operations by yourself. If you still want to add it yourself, leave the 2 models as they are and reorder the properties in the joining table to honor the convention or the DB might get messy, in that case edit it to

    {
        [Key, Column(Order = 1)]
        public string UserId { get; set; }
        public ApplicationUser User { get; set; }
    
        [Key, Column(Order = 2)]
        public int ProjectId { get; set; }
        public Project Project { get; set; }
    }
    

    To get a user's list of projects you can simply access the list in the model (make sure it's included when querying the user from the DB)


    Your assumption is correct, depending on which approach you will take, either create a new UserProject containing the Ids, or add a Project to User.Projects list.