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

IdentityUser.Update主键重复报错修复:不修改用户名更新用户属性

问题描述

报错信息:IdentityUser.Update(user) 存在另一个同类型实体拥有相同主键值。

提交编辑请求时,修改UserName无报错,但不修改用户名时触发该错误,核心代码如下:

[HttpPost]
public ActionResult Edit(ApplicationUser user, string password)
{  
    if(password.IsEmpty() == false)
    {
        user.PasswordHash = userManager.PasswordHasher.HashPassword(password);
    }
    user.Status = Enums.DataStatus.Updated;

    var result =userManager.Update(user);  // 报错位置!

    return RedirectToAction("EmployeeList");
}

问题原因

本质是EF实体跟踪冲突:当不修改UserName时,ModelBinding生成的user是全新实例,但主键与数据库中已存在的用户一致。此时DbContext可能已经通过之前的操作(比如登录用户查询、页面加载时的用户数据查询)跟踪了同主键的ApplicationUser实体,EF不允许上下文同时跟踪两个主键相同的同类型实体,因此调用Update时触发错误。

而修改UserName时,EF内部逻辑因属性变化未触发跟踪冲突,所以能正常执行。

解决方案

方案1:先获取跟踪实体再更新属性(推荐)

这种方式明确控制更新字段,完全避免跟踪冲突,也是最稳妥的做法:

[HttpPost]
public async Task<ActionResult> Edit(ApplicationUser inputUser, string password)
{  
    // 从UserManager获取数据库中当前的用户实体(该实体已被上下文跟踪)
    var dbUser = await userManager.FindByIdAsync(inputUser.Id.ToString());
    if (dbUser == null)
    {
        return NotFound();
    }

    // 按需更新属性
    if (!string.IsNullOrEmpty(password))
    {
        dbUser.PasswordHash = userManager.PasswordHasher.HashPassword(password);
    }
    dbUser.Status = Enums.DataStatus.Updated;
    // 如需修改其他属性,比如Email、昵称等,直接在这里赋值
    // dbUser.Email = inputUser.Email;

    // 更新已跟踪的实体
    var result = await userManager.UpdateAsync(dbUser);

    return RedirectToAction("EmployeeList");
}

方案2:手动处理实体状态(适合简单更新场景)

如果不想提前查询实体,可以手动处理实体的跟踪状态,但要注意避免覆盖不需要更新的字段:

[HttpPost]
public ActionResult Edit(ApplicationUser user, string password)
{  
    if(!string.IsNullOrEmpty(password))
    {
        user.PasswordHash = userManager.PasswordHasher.HashPassword(password);
    }
    user.Status = Enums.DataStatus.Updated;

    // 检查上下文是否已跟踪该实体
    var trackedUser = userManager.Users.Local.FirstOrDefault(u => u.Id == user.Id);
    if (trackedUser != null)
    {
        // 将传入的属性值复制到已跟踪的实体上
        userManager.Context.Entry(trackedUser).CurrentValues.SetValues(user);
    }
    else
    {
        // 未跟踪则附加实体并标记为修改状态
        userManager.Context.Attach(user);
        userManager.Context.Entry(user).State = EntityState.Modified;
    }

    var result = userManager.Update(user);

    return RedirectToAction("EmployeeList");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:50:25