Blazor Server添加Saving触发主键重复异常,请求技术支援
问题分析与解决方案
根本原因
EF Core的DbSet.Add()方法会递归遍历所有关联的导航属性,如果关联实体没有被当前DbContext跟踪(比如你的CurrentUser是通过级联参数传递的脱离上下文对象),EF会默认将这些实体标记为Added状态,尝试插入到数据库中,这就导致了已存在的ApplicationUser和Currency主键重复的异常。
解决方法
方法1:仅设置外键,不赋值导航属性
你已经设置了SavingObject.ApplicationUserID = CurrentUser!.ApplicationUserID,这已经足够建立关联,不需要再赋值ApplicationUser导航属性。修改业务逻辑代码:
else { SavingObject = new Saving(); // 移除这行:SavingObject.ApplicationUser = CurrentUser!; SavingObject.ApplicationUserID = CurrentUser!.ApplicationUserID; await savingsservice.Add(SavingObject); DataChanged(); }
这种方法最简单,EF只需要外键就能建立关联,不会触发对导航属性实体的插入操作。
方法2:将关联实体附加到上下文并标记为已存在
如果你确实需要保留ApplicationUser导航属性,可以在添加Saving之前,将CurrentUser和它关联的Currency附加到DbContext,告诉EF这些实体已经存在于数据库中:
修改SavingsService的Add方法:
public async Task<Saving> Add(Saving saving) { if (saving.ApplicationUser != null) { // 附加用户并标记为未修改(已存在) _context.Attach(saving.ApplicationUser).State = EntityState.Unchanged; // 如果用户关联了Currency,同样附加并标记 if (saving.ApplicationUser.Currency != null) { _context.Attach(saving.ApplicationUser.Currency).State = EntityState.Unchanged; } } _context.Savings.Add(saving); await _context.SaveChangesAsync(); return saving; }
方法3:从当前上下文重新查询跟踪的用户实体
避免使用脱离上下文的CurrentUser,而是通过用户ID从数据库重新查询(此时查询到的实体是被当前DbContext跟踪的),再关联到SavingObject:
// 假设你有用户服务,或者直接在SavingsService里添加查询用户的方法 var trackedUser = await userService.GetById(CurrentUser!.ApplicationUserID); SavingObject = new Saving(); SavingObject.ApplicationUser = trackedUser; SavingObject.ApplicationUserID = trackedUser.ApplicationUserID; await savingsservice.Add(SavingObject);
额外检查点
确保你在DbContext中正确配置了ApplicationUser和Currency的关系,否则EF可能无法正确识别外键:
modelBuilder.Entity<ApplicationUser>() .HasOne(a => a.Currency) .WithMany(c => c.ApplicationUsers) .HasForeignKey(a => a.CurrencyID) .OnDelete(DeleteBehavior.Restrict); // 根据业务需求设置删除行为
内容的提问来源于stack exchange,提问作者martin swanepoel
相关产品推荐
相关产品推荐

