ASP.NET Core中如何将用户模型自增Id赋值给商户模型的UserId外键
解决方案
EF Core处理自增主键关联外键的场景有两种常用实现方式:
方案1:使用EF Core导航属性自动关联(推荐)
利用EF Core的导航属性级联插入能力,不需要手动赋值外键,框架会自动处理主键和外键的映射:
- 修改
EntityMapper类中FromRegisterDtoToMerchant方法,去掉UserId的赋值逻辑:
public Merchant FromRegisterDtoToMerchant(RegisterDto register) { Merchant merchant = new Merchant() { MerchantName = register.MerchantName, AccountNumber = register.AccountNumber }; return merchant; }
- 修改
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
相关产品推荐
相关产品推荐

