如何实现用户批量加入组?现有逻辑优化需求
批量处理多组用户添加的实现方案
针对你已实现单组添加用户的逻辑,以下是批量处理多组用户添加的具体解决方案,兼顾性能与可读性:
1. 定义批量请求/响应模型
先构建支持批量操作的视图模型,明确输入输出结构:
// 复用你已有的单组添加请求模型 public class AddUserToGroupViewModel { public int GroupId { get; set; } public List<string> UserId { get; set; } } // 批量请求模型:包含多组添加任务 public class BatchAddUserToGroupViewModel { public List<AddUserToGroupViewModel> GroupUserRequests { get; set; } } // 批量返回结果模型:区分不同组的处理状态 public class BatchAddUserToGroupResponseViewModel { public int GroupId { get; set; } public List<AddUserToGroupResponseViewModel> UserStatuses { get; set; } }
2. 业务层实现批量处理逻辑
优化数据库查询次数,避免循环中重复调用DB,同时复用核心校验逻辑:
public async Task<List<BatchAddUserToGroupResponseViewModel>> BatchAddUserToGroupAsync(BatchAddUserToGroupViewModel batchModel) { var batchResults = new List<BatchAddUserToGroupResponseViewModel>(); if (batchModel?.GroupUserRequests == null || !batchModel.GroupUserRequests.Any()) { return batchResults; } // 一次性查询所有待处理的有效组,减少多次DB调用 var groupIds = batchModel.GroupUserRequests.Select(r => r.GroupId).Distinct(); var validGroupIds = await this.lmsMasterRepository.GetListAsync<Group>(g => groupIds.Contains(g.Id) && !g.IsDeleted && g.IsActive) .ConfigureAwait(false) .Select(g => g.Id) .ToListAsync(); // 一次性查询所有待处理的有效用户 var allUserIds = batchModel.GroupUserRequests.SelectMany(r => r.UserId).Distinct(); var validUserIds = await this.lmsMasterRepository.GetListAsync<User>(u => allUserIds.Contains(u.Id) && !u.IsDeleted && u.IsActive) .ConfigureAwait(false) .Select(u => u.Id) .ToListAsync(); // 一次性查询所有组已存在的用户关系,替代多次调用GetAllUsersInGroup var existingUserGroups = await this.lmsMasterRepository.GetListAsync<UserGroup>(ug => validGroupIds.Contains(ug.GroupId)) .ConfigureAwait(false) .GroupBy(ug => ug.GroupId) .ToDictionary(g => g.Key, g => g.Select(ug => ug.UserId).ToList()); foreach (var groupRequest in batchModel.GroupUserRequests) { var groupResult = new BatchAddUserToGroupResponseViewModel { GroupId = groupRequest.GroupId, UserStatuses = new List<AddUserToGroupResponseViewModel>() }; // 校验组是否有效 if (!validGroupIds.Contains(groupRequest.GroupId)) { groupResult.UserStatuses.Add(new AddUserToGroupResponseViewModel { Status = $"组 {groupRequest.GroupId} 无效或已删除" }); batchResults.Add(groupResult); continue; } // 获取当前组已存在的用户列表 existingUserGroups.TryGetValue(groupRequest.GroupId, out var existingUsersInGroup); existingUsersInGroup ??= new List<string>(); // 筛选出符合条件的待添加用户:有效且未在组内 var usersToAdd = groupRequest.UserId .Where(userId => validUserIds.Contains(userId) && !existingUsersInGroup.Contains(userId)) .ToList(); // 批量创建用户组关系 if (usersToAdd.Any()) { var userGroups = usersToAdd.Select(userId => new UserGroup { UserId = userId, GroupId = groupRequest.GroupId, CreatedDate = DateTime.UtcNow }).ToList(); await this.lmsMasterRepository.CreateRangeAsync<UserGroup>(userGroups).ConfigureAwait(false); } // 整理添加失败的用户状态 var failedUsers = groupRequest.UserId .Except(usersToAdd) .Select(userId => new AddUserToGroupResponseViewModel { UserId = userId, Status = validUserIds.Contains(userId) ? "用户已在组内" : "用户无效或已删除" }); groupResult.UserStatuses.AddRange(failedUsers); batchResults.Add(groupResult); } // 统一提交所有变更,保障事务一致性 await this.lmsMasterRepository.SaveAsync().ConfigureAwait(false); return batchResults; }
3. 仓储层添加批量创建方法
为提升性能,给仓储层新增批量创建实体的方法,替代循环调用单个CreateAsync:
public async Task CreateRangeAsync<T>(List<T> entities) where T : class { await this.MasterContext.Set<T>().AddRangeAsync(entities).ConfigureAwait(false); }
核心优化说明
- 减少DB往返:一次性查询所有待验证的组、用户及已有组关系,避免循环中重复访问数据库,大幅提升批量处理性能。
- 事务保障:统一在最后调用SaveAsync,确保所有批量操作要么全部提交,要么全部回滚(基于DbContext的SaveChangesAsync天然支持事务)。
- 清晰的结果反馈:区分每个组的处理状态,明确每个用户的失败原因,便于调用方排查问题。
如果你的需求是循环调用原有单组方法处理多组,直接遍历调用AddUserToGroupAsync即可,但上述方案的性能更优,适合大规模批量操作。
内容的提问来源于stack exchange,提问作者user19181303
相关产品推荐
相关产品推荐

