You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为单个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:50:11