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

EF Core 6中忽略并发冲突批量更新Wallet表TournamentId为Null的最佳实践

最佳实践方案与代码修正

现有代码的核心问题

  1. 无过滤逻辑:原SQL会将所有Wallet的TournamentId置空,完全不符合"仅处理已结束锦标赛关联钱包"的需求
  2. 错误的SQL执行方式:FromSqlRaw用于查询数据,不会执行更新操作,SaveChangesAsync也不会提交任何变更
  3. 无效的并发处理:循环重试逻辑完全多余,因为根本没有跟踪实体变更,不会触发DbUpdateConcurrencyException

方案1:原生SQL批量更新(性能最优)

直接通过数据库执行批量更新,无需加载实体,适合大量数据场景,天然忽略其他字段的并发变更:

private async Task CloseTournamentWallets(int tournamentId)
{
    // 可选:先校验锦标赛是否已结束(根据业务逻辑调整)
    var tournament = await _context.Tournaments.FindAsync(tournamentId);
    if (tournament == null || tournament.EndDate > DateTime.UtcNow || tournament.IsActive)
    {
        return;
    }

    // 仅更新指定锦标赛关联的钱包
    var affectedRows = await _context.Database.ExecuteSqlRawAsync(
        "UPDATE Wallets SET TournamentId = NULL WHERE TournamentId = @TournamentId",
        new SqlParameter("@TournamentId", tournamentId));
    
    // 可选:记录更新行数用于日志
    // _logger.LogInformation("更新了 {Count} 个钱包的锦标赛关联,锦标赛ID:{Id}", affectedRows, tournamentId);
}

优势:

  • 性能极高,直接在数据库层操作,避免内存加载大量实体
  • 天然忽略并发:仅修改TournamentId字段,不依赖Total/Available的原始值,其他事务修改这两个字段不影响更新

方案2:EF Core原生批量更新(强类型安全)

使用EF Core 6.x自带的ExecuteUpdateAsync API,无需手写SQL,编译时强类型检查:

private async Task CloseTournamentWallets(int tournamentId)
{
    // 可选:校验锦标赛状态
    var tournament = await _context.Tournaments.FindAsync(tournamentId);
    if (tournament == null || tournament.EndDate > DateTime.UtcNow || tournament.IsActive)
    {
        return;
    }

    // EF Core原生批量更新语法
    var affectedRows = await _context.Wallets
        .Where(w => w.TournamentId == tournamentId)
        .ExecuteUpdateAsync(s => s.SetProperty(w => w.TournamentId, null));
    
    // 可选:日志记录
    // _logger.LogInformation("更新了 {Count} 个钱包的锦标赛关联,锦标赛ID:{Id}", affectedRows, tournamentId);
}

优势:

  • 强类型编译校验,避免SQL拼写错误
  • 与EF Core上下文集成,自动处理参数化查询,防止SQL注入
  • 性能与原生SQL接近,同样忽略其他字段的并发变更

并发冲突处理说明

需求要求忽略Total/Available字段的并发变更,上述两个方案均满足:

  • 两种方案都是直接修改TournamentId字段,数据库UPDATE操作会直接覆盖该值,不受其他字段变更影响
  • 无需捕获DbUpdateConcurrencyException,因为没有加载实体并依赖其原始值进行修改,不会触发乐观并发异常

内容的提问来源于stack exchange,提问作者B Dimitrov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:55:18