我具有这段代码来查找UserInfo
,并在UserRole
中查找用户角色,并从Role
中查找角色信息。
我正在使用身份表。
这是我的代码:
public virtual async Task<ActionResult<List<User>>> GetuserList(CancellationToken cancellationToken)
{
var userDto = new UserDto();
var users = await userManager.Users.Include(x => x.UserRoles).ThenInclude(t=>t.Role).ToListAsync();
return users;
}
但是此代码不利于性能,因为第一步获取所有用户信息userManager.Users
,第二步查找所有user role
信息并再次查找所有用户信息.Include(x => x.UserRoles)
并查找所有角色信息.ThenInclude(t=>t.Role)
。
我只需要roleID
中的UserRole
和roleName
中的Role
。
我应该怎么做才能加载必填信息而不是全部?
更新代码:
我写这段代码:
var users = userManager.Users.Select(x => new UserDto
{
UserName = x.UserName,
Email = x.Email,
Family = x.Family,
Name = x.Name,
Password = x.PasswordHash,
PhoneNumber = x.PhoneNumber,
RoleId = x.UserRoles.FirstOrDefault(t => t.UserId == x.Id).UserId
});
但是我仍然需要在RoleName
上找到RoleTabel
,但是它不能使用Include
中的Select
。我如何使用find RoleName
????
答案 0 :(得分:1)
在调用ToListAsync()
直到在数据源上执行查询之前,您可以使用Include
,ThenInclude
,Select
,Where
等来塑造查询..功能。
您应该做的只是将您的第一个查询与更新中的投影结合在一起。
public virtual async Task<ActionResult<List<User>>> GetuserList(CancellationToken cancellationToken)
{
var userDto = new UserDto();
var users = await userManager.Users.Include(x => x.UserRoles).ThenInclude(t=>t.Role)
.Select(x => new UserDto
{
UserName = x.UserName,
Email = x.Email,
Family = x.Family,
Name = x.Name,
Password = x.PasswordHash,
PhoneNumber = x.PhoneNumber,
RoleId = x.UserRoles.FirstOrDefault(t => t.UserId == x.Id).UserId
})
.ToListAsync();
return users;
}
答案 1 :(得分:1)
要从嵌套的子表引用中进行选择,我使用的方法是选择一个匿名类型以构建有效的查询,然后再将其减少到DTO中。
例如:
var users = userManager.Users.Select(x => new
{
UserName = x.UserName,
Email = x.Email,
Family = x.Family,
Name = x.Name,
Password = x.PasswordHash,
PhoneNumber = x.PhoneNumber,
Role = x.UserRoles.Select(r => new { r.RoleId, r.Role.RoleName}).FirstOrDefault()
}).ToList()
.Select(x => new UserDto
{
UserName = x.UserName,
Email = x.Email,
Family = x.Family,
Name = x.Name,
Password = x.PasswordHash,
PhoneNumber = x.PhoneNumber,
RoleId = x.Role?.RoleId,
RoleName = x.Role?.RoleName
}).ToList();
您可以使用单个.Select
来解决问题,尽管这可能会导致SQL效率降低,因为每个内部.FirstOrDefault()
等都可能会重新加入UserRole / Role表。这样,第一个.Select()
为包含我们需要的子数据的嵌套结构构建SQL,然后第二个对生成的POCO匿名类型进行操作以构造要返回的平面DTO。
最后一件事,当使用.First()
/ .FirstOrDefault()
时,如果只希望一个条目中的一个条目,则应使用.OrderBy()
子句以确保可预测的结果。
此外,鉴于我们正在使用.Select()
来映射输出,因此您无需使用.Include()
从相关实体中进行选择。您也不需要User.UserRoles中的.Where()
子句。 (User.UserRoles仅包含该UserId的UserRoles。)在从DbContext连接松散关联的表时,将看到.Where()
子句。最好通过映射的FK直接关联实体关系。
编辑:由于每个用户可能没有角色,因此在第二个.Select()
中,您需要使用“?”。操作员检索角色ID和名称。这意味着DTO角色ID必须可以为空。如果您想默认使用RoleId为0或类似的值,则可以使用RoleId = x.Role?.RoleId ?? 0
答案 2 :(得分:0)
我有一些类似的东西,希望能有所帮助。效果很好
if (users != null && users.Length > 0 )
{
foreach (var item in users)
{
var userRoles = await UserManager.GetRolesAsync(item);
if (userRoles.Contains("Foreman"))
{
CW.AddRange(db.CrewMemberForeman.Where(x => x.AssignedForemanId == item).Select(x => x.CrewMember).OrderBy(x => x.FirstName).ToList());
}
}
}