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

EF Core使用Identity时出现FOREIGN KEY约束冲突如何修复

问题描述

我尝试使用Microsoft.AspNetCore.Identity生成id用于填充userData.AspNetUserID属性时,控制台抛出如下错误:

System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_AspNetUserRoles_AspNetUsers_UserId". The conflict occurred in database "JET", table "dbo.AspNetUsers", column 'Id'.

相关实现代码如下:

public async Task<IActionResult> CopyUserRole(int id)
{ 
    var result  = _context.UserData.Where(m => m.UserDataID == id).FirstOrDefault();
    var userData = new UserData();
    var email = result.Email.Insert(0, "copy-");

    var user = new ApplicationUser { UserName = email, Email = email };
    var UserManager = await _userManager.CreateAsync(user, "12345678");

    if(!await _roleManager.RoleExistsAsync(result.Role))
    {
        await _roleManager.CreateAsync(new IdentityRole(result.Role));
    }

    var success = await _userManager.AddToRoleAsync(user, result.Role);

    //userData.UserDataID     = 0;
    userData.AspNetUserID   = user.Id;
    userData.DeviceID       = result.DeviceID;
    userData.PhotoUrl       = result.PhotoUrl;
    userData.Status         = result.Status;
    userData.Role           = result.Role;
    userData.Name           = result.Name+" - Copy";
    userData.Area           = result.Area;
    userData.FilePhotoURL1  = result.FilePhotoURL1;
    userData.Email          = email;
    userData.LihatJurnal    = result.LihatJurnal;
    userData.UserDataArea   = result.UserDataArea;
    userData.UserDataMenu   = result.UserDataMenu;
    userData.UserDataGudang = result.UserDataGudang;
    userData.UserDataPerkiraan = result.UserDataPerkiraan;

    try
    {
        _context.UserData.Add(userData);
        await _context.SaveChangesAsync();
    }
    catch(Exception Ex)
    {
        Console.WriteLine("\n ======================== \n");
        Console.WriteLine("\n " + Ex + " \n");
        Console.WriteLine("\n ======================== \n");
    }

    return Json(userData);
}
错误原因

这个外键冲突的核心原因是代码完全没检查_userManager.CreateAsync的执行结果:

  • 如果用户创建失败(比如密码不符合规则、邮箱重复、用户名校验不通过),user对象不会被持久化到AspNetUsers表中,此时user.Id是默认的空值/临时值,根本不存在于用户表
  • 后续直接调用AddToRoleAsync给不存在的用户绑定角色,插入AspNetUserRoles表时就会触发外键约束报错,因为关联的UserId在用户表里找不到

代码里还有两个隐藏问题:

  • 没有判断查询出来的result是否为null,如果传入的id不存在,后续访问result.Email会直接抛空引用异常
  • 角色创建、用户绑定角色的操作结果也没有校验,任意一步失败都会导致后续逻辑出错
修复方案

调整代码逻辑,每一步异步操作都先判断执行结果,失败时直接返回错误,不要继续往下走:

public async Task<IActionResult> CopyUserRole(int id)
{ 
    // 先判断源数据是否存在
    var result  = _context.UserData.FirstOrDefault(m => m.UserDataID == id);
    if (result == null)
    {
        return Json(new { success = false, message = "待复制的用户不存在" });
    }

    var userData = new UserData();
    var email = result.Email.Insert(0, "copy-");

    var user = new ApplicationUser { UserName = email, Email = email };
    // 检查用户创建结果
    var createUserResult = await _userManager.CreateAsync(user, "12345678");
    if (!createUserResult.Succeeded)
    {
        return Json(new { success = false, message = "用户创建失败", errors = createUserResult.Errors });
    }

    // 检查角色是否存在,不存在则创建
    if(!await _roleManager.RoleExistsAsync(result.Role))
    {
        var createRoleResult = await _roleManager.CreateAsync(new IdentityRole(result.Role));
        if (!createRoleResult.Succeeded)
        {
            return Json(new { success = false, message = "角色创建失败", errors = createRoleResult.Errors });
        }
    }

    // 检查用户绑定角色结果
    var addToRoleResult = await _userManager.AddToRoleAsync(user, result.Role);
    if (!addToRoleResult.Succeeded)
    {
        return Json(new { success = false, message = "用户角色绑定失败", errors = addToRoleResult.Errors });
    }

    // 所有Identity操作成功后,再给UserData赋值
    userData.AspNetUserID   = user.Id;
    userData.DeviceID       = result.DeviceID;
    userData.PhotoUrl       = result.PhotoUrl;
    userData.Status         = result.Status;
    userData.Role           = result.Role;
    userData.Name           = result.Name + " - Copy";
    userData.Area           = result.Area;
    userData.FilePhotoURL1  = result.FilePhotoURL1;
    userData.Email          = email;
    userData.LihatJurnal    = result.LihatJurnal;
    userData.UserDataArea   = result.UserDataArea;
    userData.UserDataMenu   = result.UserDataMenu;
    userData.UserDataGudang = result.UserDataGudang;
    userData.UserDataPerkiraan = result.UserDataPerkiraan;

    try
    {
        _context.UserData.Add(userData);
        await _context.SaveChangesAsync();
    }
    catch(Exception Ex)
    {
        Console.WriteLine("\n ======================== \n");
        Console.WriteLine("\n " + Ex + " \n");
        Console.WriteLine("\n ======================== \n");
        return Json(new { success = false, message = "用户数据保存失败" });
    }

    return Json(new { success = true, data = userData });
}

额外注意:代码里设置的初始密码是12345678,要确认和Startup.cs/Program.cs里配置的Identity密码规则匹配,比如是否要求特殊字符、大小写、数字长度,否则会一直出现用户创建失败的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:27:17