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

Asp.Net Core Identity更新角色遇跟踪冲突异常求助

解决Microsoft.AspNetCore.Identity.EntityFrameworkCore角色更新时的跟踪冲突异常

错误原因

  • 你通过AsNoTracking()查询到的角色实体处于无跟踪状态,但后续用command.Adapt<RoleEntity>(config)创建了全新的RoleEntity实例并覆盖了原变量。
  • 调用_role.UpdateAsync(model)时,这个新实例的Id与数据库中已存在的角色Id一致,而DbContext此时可能已在跟踪相同Id的实体(或Identity内部跟踪逻辑导致),最终触发跟踪冲突。

解决方案

方案一:直接修改跟踪实体(推荐)

去掉AsNoTracking(),查询处于跟踪状态的实体,直接更新其属性后提交:

public async Task<Result> UpdateRoleAsync(UpdateRoleCommand command, CancellationToken cancellation)
{
    var model = await _role.Roles.SingleOrDefaultAsync(s => s.Id == command.Id, cancellation);
    if(model == null)
    {
        return Result.Fail(FailMessage.Internal);
    }
    // 将命令中的属性值映射到已跟踪的实体上
    model.Name = command.Name;
    model.PresianName = command.PresianName;
    // 同步更新Identity角色必填的NormalizedName(也可由Identity自动处理)
    model.NormalizedName = command.Name.ToUpperInvariant();
    
    var result = await _role.UpdateAsync(model);
    if (result.Succeeded)
    {
        return Result.Success();
    }
    // 高效拼接错误信息
    string error = string.Join("\n", result.Errors.Select(e => e.Description));
    return Result.Fail(error);  
}

方案二:附加实体并标记修改状态(适配无跟踪场景)

如果必须使用无跟踪查询,需将新创建的实体附加到DbContext并标记为修改状态:

public async Task<Result> UpdateRoleAsync(UpdateRoleCommand command, CancellationToken cancellation)
{
    var existingModel = await _role.Roles.AsNoTracking().SingleOrDefaultAsync(s => s.Id == command.Id, cancellation);
    if(existingModel == null)
    {
        return Result.Fail(FailMessage.Internal);
    }
    // 创建实体实例并赋值,保留Identity角色的必填属性
    var model = new RoleEntity
    {
        Id = existingModel.Id,
        Name = command.Name,
        PresianName = command.PresianName,
        NormalizedName = existingModel.NormalizedName,
        ConcurrencyStamp = existingModel.ConcurrencyStamp // 并发令牌,防止更新冲突
    };
    
    // 将实体附加到上下文并标记为已修改
    _context.Attach(model).State = EntityState.Modified;
    
    var result = await _role.UpdateAsync(model);
    if (result.Succeeded)
    {
        return Result.Success();
    }
    string error = string.Join("\n", result.Errors.Select(e => e.Description));
    return Result.Fail(error);  
}

注意事项

  • Identity角色实体(如IdentityRole)包含NormalizedName、ConcurrencyStamp等系统必填属性,更新时需确保这些属性值正确,否则会触发验证失败。
  • 避免每次方法调用都创建新的TypeAdapterConfig,建议全局初始化一次AutoMapper配置,提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 18:17:38