如何为单个Campaign批量分配用户并跳过已关联用户?
单个Campaign批量分配用户(自动跳过已关联用户)
需求
为单个Campaign选择多个用户进行分配,若用户已被分配至该Campaign则自动跳过。
现有实现代码
Controller 层
[HttpPost, ActionName("Create")] [ValidateAntiForgeryToken] public async Task<ActionResult> Create(AssignCampainToUserViewModel model) { try { var result = await this._employeeService.AssignCampaignToUserAsync(model); if (result) { return RedirectToAction(nameof(Create)); } return View("Error"); } catch { return View("Error"); } }
Service 层
public async Task<bool> AssignCampaignToUserAsync(AssignCampainToUserViewModel model) { var checkUserHasCapain = await this._UserRepositery .CheckUserAssignCompaignAsync(model.UserId, model.CampaignId) .ConfigureAwait(false); if (checkUserHasCapain != null) { var userCampaign = new AssigningCampainCustomModel() { UserId = checkUserHasCapain, CampaignId = model.CampaignId, }; await this._UserRepositery .AssignCampaigToUserAsync(userCampaign) .ConfigureAwait(false); await this._UserRepositery .Save() .ConfigureAwait(false); return true; } return false; } }
Repository 层 - 校验未关联用户方法
public async Task <IList<int>> CheckUserAssignCompaignAsync(IList<int> UserId, int CampaignId) { var campainByUserId = from users in this._userMasterContext.User where UserId.Contains(users.UserId) && users.IsActive &&!users.IsDeleted join campaign in this._userMasterContext. Campaign on CampaignId equals campaign.CampaignId where campaign.IsActive == true && !campaign.IsDeleted && !(from userCampaign in this._userMasterContext. UserCampaign userCampaign.CampaignId == CampaignId select userCampaign.UserId).ToList().Contains(users.UserId) select users.UserId; return await campainByUserId.ToListAsync(); }
Repository 层 - 分配用户方法
public async Task AssignCampaigToUserAsync(AssigningCampainCustomModel model) { if(model.UserId !=null) { foreach (var user in model.UserId) { UserCampaign userCampaign = new UserCampaign() { UserId = user, CampaignId = model.CampaignId, }; await this._userMasterContext .UserCampaign .AddRangeAsync(userCampaign); } } }
问题修正与优化
现有代码存在语法错误、性能问题及逻辑判断不当,以下是修正后的完整实现:
1. 修正 Repository 层校验方法(修复语法错误+性能优化)
修正拼写错误,优化LINQ查询,避免子查询中提前调用ToList(),改用Any()提升查询效率:
// 修正拼写错误:Compaign → Campaign public async Task<IList<int>> CheckUserAssignCampaignAsync(IList<int> userIds, int campaignId) { // 先校验Campaign是否有效 var validCampaign = await _userMasterContext.Campaign .AnyAsync(c => c.CampaignId == campaignId && c.IsActive && !c.IsDeleted) .ConfigureAwait(false); if (!validCampaign) { return new List<int>(); } // 查询符合条件的未关联用户ID var unassignedUserIds = await _userMasterContext.User .Where(u => userIds.Contains(u.UserId) && u.IsActive && !u.IsDeleted) .Where(u => !_userMasterContext.UserCampaign .Any(uc => uc.UserId == u.UserId && uc.CampaignId == campaignId)) .Select(u => u.UserId) .ToListAsync() .ConfigureAwait(false); return unassignedUserIds; }
2. 修正 Service 层逻辑判断
修正拼写错误,将checkUserHasCapain != null改为判断列表是否有元素,避免空列表误判:
public async Task<bool> AssignCampaignToUserAsync(AssignCampainToUserViewModel model) { // 修正拼写错误,调用修正后的方法 var unassignedUserIds = await _UserRepositery .CheckUserAssignCampaignAsync(model.UserId, model.CampaignId) .ConfigureAwait(false); // 判断是否有未关联的用户需要分配 if (unassignedUserIds.Any()) { var assignModel = new AssigningCampainCustomModel() { UserId = unassignedUserIds, CampaignId = model.CampaignId, }; await _UserRepositery.AssignCampaigToUserAsync(assignModel) .ConfigureAwait(false); await _UserRepositery.Save() .ConfigureAwait(false); return true; } return false; }
3. 优化 Repository 层分配方法
避免循环调用AddRangeAsync,直接批量创建实体后一次性添加,提升性能:
// 修正拼写错误:Campaig → Campaign public async Task AssignCampaignToUserAsync(AssigningCampainCustomModel model) { if(model.UserId?.Any() != true) { return; } // 批量创建UserCampaign实体 var userCampaigns = model.UserId.Select(userId => new UserCampaign() { UserId = userId, CampaignId = model.CampaignId, // 可添加创建时间等默认字段 CreatedDate = DateTime.UtcNow }).ToList(); // 一次性添加所有实体 await _userMasterContext.UserCampaign.AddRangeAsync(userCampaigns) .ConfigureAwait(false); }
关键优化点
- 语法修正:修正多处拼写错误(如
Compaign→Campaign),修复LINQ查询的语法问题 - 性能提升:将子查询中的
ToList().Contains()改为Any(),减少内存占用与查询耗时;批量添加实体而非循环单条添加 - 逻辑严谨:先校验Campaign有效性,避免无效操作;判断列表是否有元素而非是否为null,避免空列表误判
- 代码可读性:规范变量命名,拆分复杂LINQ查询为更清晰的结构
内容的提问来源于stack exchange,提问作者Surbhi
相关产品推荐
相关产品推荐

