更新含子对象集合的Account时触发SQLite非空约束异常,如何解决?
解决EF Core中RefreshToken.AccountId非空约束报错的问题
出现SQLite Error 19: 'NOT NULL constraint failed: RefreshTokens.AccountId'的核心原因是EF Core未自动识别并填充RefreshToken与Account的关联外键,通常由实体配置或数据操作方式不正确导致,以下是具体解决办法:
1. 确保实体类关联配置正确
必须显式定义外键字段和导航属性,让EF Core明确识别一对多关系:
Account实体类:
public class Account { public int Id { get; set; } // 其他业务属性 // 初始化集合避免空引用 public ICollection<RefreshToken> RefreshTokens { get; set; } = new List<RefreshToken>(); }
RefreshToken实体类:
public class RefreshToken { public int Id { get; set; } public string Token { get; set; } public DateTime Expires { get; set; } // 显式声明外键字段,需与Account主键类型匹配 public int AccountId { get; set; } // 导航属性,关联到Account public Account Account { get; set; } }
2. 用Fluent API明确配置关联规则
在DataContext的OnModelCreating方法中强制指定外键约束,避免EF Core自动推断出错:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Account>() .HasMany(account => account.RefreshTokens) // Account拥有多个RefreshToken .WithOne(token => token.Account) // 每个RefreshToken属于一个Account .HasForeignKey(token => token.AccountId) // 指定外键字段 .IsRequired() // 强制外键非空,与SQLite约束一致 .OnDelete(DeleteBehavior.Cascade); // 可选:删除Account时级联删除RefreshToken,按需调整 }
3. 修正数据操作方式
不要用_context.Update(account)添加新RefreshToken——Update会将整个Account标记为Modified,但未被上下文跟踪的新RefreshToken不会自动填充外键。正确操作分两种场景:
场景1:Account已被上下文跟踪(如刚从数据库查询)
var targetAccount = _context.Accounts.FirstOrDefault(a => a.Id == accountId); if (targetAccount != null) { var newToken = new RefreshToken { Token = "生成的刷新令牌", Expires = DateTime.UtcNow.AddDays(7) }; targetAccount.RefreshTokens.Add(newToken); // 直接SaveChanges,EF会自动填充AccountId并插入数据 _context.SaveChanges(); }
场景2:Account未被上下文跟踪(如前端传入的DTO转换而来)
不要直接使用传入对象,从数据库查询最新实体再操作:
var existingAccount = _context.Accounts.Find(inputAccount.Id); if (existingAccount != null) { var newToken = new RefreshToken { Token = "xxx", Expires = DateTime.UtcNow.AddDays(7) }; existingAccount.RefreshTokens.Add(newToken); _context.SaveChanges(); }
4. 验证数据库迁移(可选)
若之前的迁移未正确生成外键约束,重新生成并更新数据库:
# 生成新迁移 Add-Migration FixRefreshTokenForeignKey # 更新数据库 Update-Database
内容的提问来源于stack exchange,提问作者janci
相关产品推荐
相关产品推荐

