I want to find a single User
and populate the ICollection<Role>
for that user
I've got users
public class User {
public string Id { get; set; }
public string UserName { get; set; }
public ICollection<Role> Roles { get; set; }
}
And the roles
public class Role {
public string Id {get; set; }
public string Name { get; set; }
}
My Database looks like this
I want to get a specific User by Id, all his Roles with a single SQL call.
_context is my DbContext where we can queue User, Roles and UserRoles
With the following sql command I get what data I'm looking for
from users in _context.Users
where users.Id == id
join userRoles in _context.UserRoles on users.Id equals userRoles.UserId
join roles in _context.Roles on userRoles.RoleId equals roles.Id
select new
{
UserID = users.Id,
UserName = users.UserName,
RoleID = roles.Id,
RoleName = roles.Name
};
My problem
I want to map this result to the User
class, it should create a single user and a ICollection
of Roles
How can I achieve this?
Would it be possible using AutoMapper? How?
Thanks in advance! Alex
PS: I do not want to use the stores offered by Identity
since there is a lot of extra information to be loaded from the database and control the number of calls to it
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace ConsoleApplication63
{
class Program
{
static void Main(string[] args)
{
Context _context = new Context() {
UserRoles = new List<UserRole>() {
new UserRole() { RoleId = "1", UserId = "1"},
new UserRole() { RoleId = "2", UserId = "3"},
new UserRole() { RoleId = "3", UserId = "2"},
new UserRole() { RoleId = "4", UserId = "4"}
},
Users = new List<User>() {
new User() {
Id = "3", UserName = "ABC", Roles = new List<Role> {
new Role() { Id = "100", Name = "ABC"},
new Role() { Id = "101", Name = "DEF"},
new Role() { Id = "102", Name = "GHI"},
new Role() { Id = "103", Name = "JKL"},
new Role() { Id = "104", Name = "MNO"}
}
}
},
Roles = new List<Role>() {
new Role() { Name = "XYZ", Id = "2"}
}
};
string id = "3";
List<UserRole> results = (from users in _context.UserRoles
where users.UserId == id
join user in _context.Users on users.UserId equals user.Id
join role in _context.Roles on users.RoleId equals role.Id
select new { Roles = user.Roles, UserId = user.Id})
.Select(x => x.Roles.Select(y => new UserRole() { RoleId = y.Id, UserId = x.UserId}).ToList()).FirstOrDefault();
}
}
public class Context
{
public List<User> Users { get; set; }
public List<Role> Roles{ get; set; }
public List<UserRole> UserRoles{ get; set; }
}
public class UserRole
{
public string UserId { get; set; }
public string RoleId { get; set; }
}
public class User {
public string Id { get; set; }
public string UserName { get; set; }
public List<Role> Roles { get; set; }
}
public class Role {
public string Id {get; set; }
public string Name { get; set; }
}
}
I think you need to use GroupBy to group your result and use an appropriate projection for the Roles collection. Considering your initial query, you could do the following (I am using the fluent syntax, you can convert it to query syntax):
var initialQuery = from users in _context.Users
where users.Id == id
join userRoles in _context.UserRoles on users.Id equals userRoles.UserId
join roles in _context.Roles on userRoles.RoleId equals roles.Id
select new
{
UserID = users.Id,
UserName = users.UserName,
RoleID = roles.Id,
RoleName = roles.Name
};
IEnumerable<User> result = initialQuery
.GroupBy(x => new { x.UserID, x.UserName })
.Select(x => new User
{
Id = x.Key.UserID,
UserName = x.Key.UserName,
Roles = x.Select(a => new Role { Id = a.RoleID, Name = a.RoleName }).ToList() as ICollection<Role>
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.