ASP.NET Core MVC Code First 如何将自动生成的主键复制到另一张表
解决方案
步骤1:配置Student主键不自动生成
首先给Student类的Id字段添加特性,关闭主键自动生成逻辑,执行迁移后更新数据库,确保Student表的Id字段没有自增属性:
using System.ComponentModel.DataAnnotations.Schema; public class Student { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] // 新增该行关闭主键自增 public int Id { get; set; } // 其余属性保持原有定义不变 }
步骤2:调整存储逻辑,先保存User获取自增Id
EF Core调用SaveChangesAsync后,会自动把数据库生成的主键值回写到对应的实体对象中,你只需要调整保存顺序,同时新增事务保证操作原子性,避免出现User保存成功但Student保存失败的脏数据问题。
修改后的服务代码如下:
public async Task<bool> RegistrationService(StudentRegisterModel registerModel) { using var transaction = await _context.Database.BeginTransactionAsync(); try { //validation functions var context = new ValidationContext(registerModel, serviceProvider: null, items: null); var results = new List<ValidationResult>(); if (Validator.TryValidateObject(registerModel, context, results, true)) { if (CheckEmailAvailability(registerModel.Email)){ if (registerModel.Password != registerModel.ConfirmPassword) return false; // 先创建保存User,获取数据库生成的自增Id User user = new User { Email = registerModel.Email, Password = Encoder(registerModel.Password), }; _context.Add(user); await _context.SaveChangesAsync(); // 此时user.Id已经被赋值为数据库生成的自增主键 // 再创建Student,将Id设置为user.Id Student student = new Student { Id = user.Id, // 同步User的自增Id FirstName = registerModel.FirstName, LastName = registerModel.LastName, Email = registerModel.Email, Guardian = registerModel.Guardian, DateOfBirth = registerModel.DateOfBirth, AdminPermition = false }; _context.Add(student); await _context.SaveChangesAsync(); await transaction.CommitAsync(); return true; } } return false; } catch { await transaction.RollbackAsync(); return false; } }
可选优化:配置一对一关联自动同步
如果Student和User本身是一对一关联的业务关系,也可以直接配置外键关联,让EF Core自动处理Id同步:
public class Student { [Key] [ForeignKey(nameof(User))] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; } public User User { get; set; } // 其余属性保持原有定义不变 }
配置后直接给Student的User导航属性赋值,保存时EF Core会自动完成Id的同步赋值。
内容的提问来源于stack exchange,提问作者user11352561
相关产品推荐
相关产品推荐

