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

ASP.NET Core中如何将用户模型自增Id赋值给商户模型的UserId外键

解决方案

EF Core处理自增主键关联外键的场景有两种常用实现方式:

方案1:使用EF Core导航属性自动关联(推荐)

利用EF Core的导航属性级联插入能力,不需要手动赋值外键,框架会自动处理主键和外键的映射:

  1. 修改EntityMapper类中FromRegisterDtoToMerchant方法,去掉UserId的赋值逻辑:
public Merchant FromRegisterDtoToMerchant(RegisterDto register)
{
    Merchant merchant = new Merchant()
    {
        MerchantName = register.MerchantName,
        AccountNumber = register.AccountNumber
    };
    return merchant;
}
  1. 修改AuthService的注册逻辑,将商户实体添加到用户的Merchants导航属性集合中,EF插入用户时会自动级联插入商户,自动填充外键:
public async Task<UserDto> register(RegisterDto register)
{
    var userExists = await _unitOfWork.UserRepository.GetByUsername(register.Username);
    if (userExists != null)
    {
        throw new Exception("User already exists!");
    }
    try
    {
        register.Password = User.ComputeSha256Hash(register.Password);
        var mapper = new EntityMapper();
        var user = mapper.FromRegisterDtoToUser(register);
        var merchant = mapper.FromRegisterDtoToMerchant(register);
        
        // 新增:关联用户和商户导航属性
        user.Merchants ??= new List<Merchant>();
        user.Merchants.Add(merchant);

        await _unitOfWork.UserRepository.Insert(user);
        // 无需单独插入商户,EF会自动级联插入
        await _unitOfWork.SaveChangesAsync();

        if (user != null)
        {
            var token = GetToken(user);
            return mapper.FromUserToUserDto(user, token);
        }
        return null;
    }
    catch (Exception e)
    {
        throw new Exception(e.Message);
    }
}

方案2:手动获取自增主键赋值

如果不希望使用级联插入,可以先插入用户并保存,拿到数据库生成的自增Id后再赋值给商户的UserId字段:
修改AuthService的注册逻辑如下:

public async Task<UserDto> register(RegisterDto register)
{
    var userExists = await _unitOfWork.UserRepository.GetByUsername(register.Username);
    if (userExists != null)
    {
        throw new Exception("User already exists!");
    }
    // 开启事务保证数据一致性
    using var transaction = await _unitOfWork.BeginTransactionAsync();
    try
    {
        register.Password = User.ComputeSha256Hash(register.Password);
        var mapper = new EntityMapper();
        var user = mapper.FromRegisterDtoToUser(register);
        
        // 先插入用户并保存,获取数据库生成的自增Id
        await _unitOfWork.UserRepository.Insert(user);
        await _unitOfWork.SaveChangesAsync();

        // 赋值UserId后插入商户
        var merchant = mapper.FromRegisterDtoToMerchant(register);
        merchant.UserId = user.Id;
        await _unitOfWork.MerchantRepository.Insert(merchant);
        await _unitOfWork.SaveChangesAsync();

        // 提交事务
        await transaction.CommitAsync();

        if (user != null)
        {
            var token = GetToken(user);
            return mapper.FromUserToUserDto(user, token);
        }
        return null;
    }
    catch (Exception e)
    {
        // 异常回滚事务
        await transaction.RollbackAsync();
        throw new Exception(e.Message);
    }
}

注意事项

方案2需要显式开启事务,避免出现用户插入成功、商户插入失败导致的数据不一致问题。如果你的UnitOfWork已经封装了事务方法,直接调用对应方法即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:24:02