我需要通过 Id 查询另一个查询返回的用户列表
I need to do a query on a returned list of users from another query, by Id
目前,我有一个从用户 table 获取用户信息的服务。用户可以由管理员或员工创建,所有这些员工都有自己的 ID。因此,考虑到这一点,有一个名为 CreatedBy 的列,其中包含此管理员或用户的 ID,我必须将其名称设为 return。到目前为止,我已经提取了用户模型,但现在我需要创建部分,在其中使用 CreatedBy
中的 user.Id 提取用户名
这是我从数据库中提取的 tables 用户和公司,查询参数只是名称或公司名称
public async Task<List<ApplicationUser>> SearchUsers(UserSearchDto userSearchDto)
{
userSearchDto.FirstName ??= string.Empty;
userSearchDto.LastName ??= string.Empty;
userSearchDto.CompanyName ??= string.Empty;
return await _locationDbContext.Users
.Include(nameof(Company))
.Where(user => user.FirstName.Contains(userSearchDto.FirstName)
&& user.LastName.Contains(userSearchDto.LastName)
&& user.Company.Company_Name.Contains(userSearchDto.CompanyName))
.ToListAsync();
}
因此,在我正在 returning 的这个列表中,我正在尝试执行另一个查询,以根据第一个服务中 returned 的 CreatedBy id 获取更多用户信息,以恢复在 CreatedBy 中具有 ID 的那些用户的名称。
var userDtos = _mapper.Map<List<ApplicationUser>, List<UserDetailsDto>>(users);
foreach (UserDetailsDto user in userDtos)
{
user.CreatedByName = await _userService
.SearchUsers(userDtos.Where(user.Id == user.CreatedBy))
}
到目前为止,我觉得这是一个可能的解决方案,但我不确定我将在哪里或如何提取它,因为该解决方案在我使用“.Where”语句时给我一个错误。也许如果我可以创建另一个服务,该服务将 return 通过 Id 代替用户并使用 createdby Id 来提取名称,但目前还不存在类似的服务。我想要 return 的模型也与代表用户 table 的模型有点不同,因为 ApplicationUser 具有 CreatedBy,它是一个 Id,但 returned 模型 userDetailsDto 将具有一个名称字符串 属性 以及我将尝试在自动映射器中分配的名称。如果我能想到如何通过 Id 分配名称。
CreateMap<ApplicationUser, UserDetailsDto>()
.ForMember(dest => dest.CompanyName,
opts => opts.MapFrom(src => src.Company.Company_Name));
理想情况下,您应该能够使用导航属性解决这个问题。如果您的用户 table 使用 CreatedBy 代表 CreatedBy 用户 ID,那么您可以调整映射以促进 CreatedBy 导航 属性:
public class User
{
public class UserId { get; set; }
// ...
public virtual User CreatedBy { get; set; }
}
然后在映射中为 FK 关联使用阴影 属性:(在 OnModelCreating 或使用 EntityTypeConfiguration 中)
EF 核心
.HasOne(x => x.CreatedBy)
.WithMany()
.HasForeignHey("CreatedBy") // Property on Users table
.Required();
EF 6
.HasRequired(x => x.CreatedBy)
.WithMany()
.Map(x => x.MapKey("CreatedBy")) // Property on Users table
或者,如果您希望用户可以访问 CreatedBy FK table,请将其映射为类似 CreatedByUserId:
的内容
public class User
{
public int UserId { get; set; }
// ...
[ForeignKey("CreatedBy"), Column("CreatedBy")]
public int CreatedByUserId { get; set; }
public virtual User CreatedBy { get; set; }
}
现在,当您去搜索您的用户时,您可以一次性投射您的 CreatedBy 用户 ID 和名称。
当谈到可选的搜索参数时,您应该尽可能将条件(if/else/ null 检查等)放在 Linq 之外。这有助于编写更高效的查询,而不是将条件逻辑嵌入到 SQL.
public async Task<List<ApplicationUserViewModel>> SearchUsers(UserSearchDto userSearchDto)
{
var query = _locationDbContext.Users.AsQueryable();
if (!string.IsNullOrEmpty(userSearchDto.FirstName))
query = query.Where(x => x.FirstName.Contains(userSearchDto.FirstName));
if (!string.IsNullOrEmpty(userSearchDto.LastName))
query = query.Where(x => x.LastName.Contains(userSearchDto.LastName));
if (!string.IsNullOrEmpty(userSearchDto.CompanyName))
query = query.Where(x => x.Company.Name.Contains(userSearchDto.CompanyName));
return await query.ProjectTo<ApplicationUserViewModel>(_config)
.ToListAsync();
}
其中 _config
反映了一个自动映射器 MapperConfiguration,其中包含有关如何将用户映射到所需视图模型的详细信息。如果您没有利用 Automapper,您可以使用 Select
来投影值来完成此操作。其他考虑因素是考虑使用 StartsWith
而不是 Contains
,可能会提供一个选项来执行更昂贵的 Contains
搜索...还添加诸如最小搜索长度检查之类的东西(即 3 + 字符)和分页或结果行限制(即 Take(50)
),以避免大量搜索请求破坏您的系统。 (即搜索名字中带有“e”的用户)
该视图模型可能有 UserId、UserName、CompanyName,然后是 CreatedByUserId、CreatedByName 之类的东西。要解决 CreatedBy 详细信息,您只需在 Automapper 配置或 Select(u => new ApplicationUserViewModel { ... })
语句中引用 u.CreatedBy.UserId 和 u.CreatedBy.Name。
目前,我有一个从用户 table 获取用户信息的服务。用户可以由管理员或员工创建,所有这些员工都有自己的 ID。因此,考虑到这一点,有一个名为 CreatedBy 的列,其中包含此管理员或用户的 ID,我必须将其名称设为 return。到目前为止,我已经提取了用户模型,但现在我需要创建部分,在其中使用 CreatedBy
中的 user.Id 提取用户名这是我从数据库中提取的 tables 用户和公司,查询参数只是名称或公司名称
public async Task<List<ApplicationUser>> SearchUsers(UserSearchDto userSearchDto)
{
userSearchDto.FirstName ??= string.Empty;
userSearchDto.LastName ??= string.Empty;
userSearchDto.CompanyName ??= string.Empty;
return await _locationDbContext.Users
.Include(nameof(Company))
.Where(user => user.FirstName.Contains(userSearchDto.FirstName)
&& user.LastName.Contains(userSearchDto.LastName)
&& user.Company.Company_Name.Contains(userSearchDto.CompanyName))
.ToListAsync();
}
因此,在我正在 returning 的这个列表中,我正在尝试执行另一个查询,以根据第一个服务中 returned 的 CreatedBy id 获取更多用户信息,以恢复在 CreatedBy 中具有 ID 的那些用户的名称。
var userDtos = _mapper.Map<List<ApplicationUser>, List<UserDetailsDto>>(users);
foreach (UserDetailsDto user in userDtos)
{
user.CreatedByName = await _userService
.SearchUsers(userDtos.Where(user.Id == user.CreatedBy))
}
到目前为止,我觉得这是一个可能的解决方案,但我不确定我将在哪里或如何提取它,因为该解决方案在我使用“.Where”语句时给我一个错误。也许如果我可以创建另一个服务,该服务将 return 通过 Id 代替用户并使用 createdby Id 来提取名称,但目前还不存在类似的服务。我想要 return 的模型也与代表用户 table 的模型有点不同,因为 ApplicationUser 具有 CreatedBy,它是一个 Id,但 returned 模型 userDetailsDto 将具有一个名称字符串 属性 以及我将尝试在自动映射器中分配的名称。如果我能想到如何通过 Id 分配名称。
CreateMap<ApplicationUser, UserDetailsDto>()
.ForMember(dest => dest.CompanyName,
opts => opts.MapFrom(src => src.Company.Company_Name));
理想情况下,您应该能够使用导航属性解决这个问题。如果您的用户 table 使用 CreatedBy 代表 CreatedBy 用户 ID,那么您可以调整映射以促进 CreatedBy 导航 属性:
public class User
{
public class UserId { get; set; }
// ...
public virtual User CreatedBy { get; set; }
}
然后在映射中为 FK 关联使用阴影 属性:(在 OnModelCreating 或使用 EntityTypeConfiguration 中)
EF 核心
.HasOne(x => x.CreatedBy)
.WithMany()
.HasForeignHey("CreatedBy") // Property on Users table
.Required();
EF 6
.HasRequired(x => x.CreatedBy)
.WithMany()
.Map(x => x.MapKey("CreatedBy")) // Property on Users table
或者,如果您希望用户可以访问 CreatedBy FK table,请将其映射为类似 CreatedByUserId:
的内容public class User
{
public int UserId { get; set; }
// ...
[ForeignKey("CreatedBy"), Column("CreatedBy")]
public int CreatedByUserId { get; set; }
public virtual User CreatedBy { get; set; }
}
现在,当您去搜索您的用户时,您可以一次性投射您的 CreatedBy 用户 ID 和名称。
当谈到可选的搜索参数时,您应该尽可能将条件(if/else/ null 检查等)放在 Linq 之外。这有助于编写更高效的查询,而不是将条件逻辑嵌入到 SQL.
public async Task<List<ApplicationUserViewModel>> SearchUsers(UserSearchDto userSearchDto)
{
var query = _locationDbContext.Users.AsQueryable();
if (!string.IsNullOrEmpty(userSearchDto.FirstName))
query = query.Where(x => x.FirstName.Contains(userSearchDto.FirstName));
if (!string.IsNullOrEmpty(userSearchDto.LastName))
query = query.Where(x => x.LastName.Contains(userSearchDto.LastName));
if (!string.IsNullOrEmpty(userSearchDto.CompanyName))
query = query.Where(x => x.Company.Name.Contains(userSearchDto.CompanyName));
return await query.ProjectTo<ApplicationUserViewModel>(_config)
.ToListAsync();
}
其中 _config
反映了一个自动映射器 MapperConfiguration,其中包含有关如何将用户映射到所需视图模型的详细信息。如果您没有利用 Automapper,您可以使用 Select
来投影值来完成此操作。其他考虑因素是考虑使用 StartsWith
而不是 Contains
,可能会提供一个选项来执行更昂贵的 Contains
搜索...还添加诸如最小搜索长度检查之类的东西(即 3 + 字符)和分页或结果行限制(即 Take(50)
),以避免大量搜索请求破坏您的系统。 (即搜索名字中带有“e”的用户)
该视图模型可能有 UserId、UserName、CompanyName,然后是 CreatedByUserId、CreatedByName 之类的东西。要解决 CreatedBy 详细信息,您只需在 Automapper 配置或 Select(u => new ApplicationUserViewModel { ... })
语句中引用 u.CreatedBy.UserId 和 u.CreatedBy.Name。