So there is a many-to-many relation between Users and Roles, and you want all (or some) Users, each with all their roles (or some of their roles).
Use the virtual ICollections!
Apparently you are using Entity Framework. If you have followed the conventions, you will have classes similar to the following:
class User
{
public int Id {get; set;}
public string name {get; set;}
...
// every User has zero or more roles (many-to-many)
public virtual ICollection<Role> Roles {get; set;}
}
class Role
{
public int Id {get; set;}
public string name {get; set;}
...
// every Role is played by zero or more Users (many-to-many)
public virtual ICollection<User> Users {get; set;}
}
It might be that you have different property names, but the most important part is the virtual ICollection<...>
. This informs entity framework about the many-to-many relation between Users and Roles.
In entity framework the columns of the tables are represented by non-virtual properties. The virtual properties represent the relations between the table (one-to-many, many-to-many, ...)
Entity framework knows the relation between the tables. If you use the collections, entity framework will automatically translate this in the proper (group-)joins.
Requirement Give me (some properties of) all Users, each with their Roles
var usersWithTheirRoles = dbContext.Users
// only if you don't want all Users:
.Where(user => user.City == "New York")
.Select(user => new
{
// Select only the User properties that you plan to use:
Id = user.Id,
Name = user.Name,
...
Roles = user.Roles
// only if you don't want all Roles
.Where(role => ...)
.Select(role => new
{
Id = role.Id,
Name = role.Name,
...
})
.ToList(),
});
Do the GroupJoin yourself
If you don't want to use the virtual ICollections, or your entity framework versions doesn't support this, consider to do the groupjoin yourself:
var result = dbContext.Users.GroupJoin(dbContext.UserRoles,
user => user.Id, // from every User take the Id
userRole => userRole.UserId, // from every UserRole take the foreign key to User
// parameter resultSelector: for every user, and its zero or more userRoles,
// make one new object, containing the following properties:
(user, userRolesOfThisUser) => new
{
Id = user.Id,
Name = usr.Name,
// for the Roles of this User: groupjoin all Roles with the UserRoles of this User
Roles = dbContext.Roles.GroupJoin(userRolesOfThisUser,
role => role.Id // from every Role take the Id,
userRole => userRole.RoleId, // from every UserRole of this user take the foreign key
// result selector: take every Role, and its zero or more UserRoles
// that are also UserRoles of this User, to make one new Role:
(role, userRolesOfThisRole) => new
{
Id = role.Id,
Name = role.Name,
})
.ToList(),
});
In my opinion the virtual ICollection
method looks way more elegant and natural.