EFCore更新实体时部分字段未赋值触发Age列非空约束报错如何解决
问题原因
- 直接调用
DbContext.Update()方法时,EF Core会默认将传入实体的所有属性标记为待更新状态,如果你传入的User对象仅填充了Id、UserName、Password字段,Age字段未赋值为null,执行更新时EF会尝试将数据库中Age字段改为null,违反你配置的非空约束,触发报错。 - 你抛出的异常提示
INSERT fails,额外说明还有可能你传入的User对象没有携带正确的Id值(比如Id为默认值0),EF会将该实体判定为新增对象执行插入操作,此时Age为null自然也不符合非空要求。
解决方案
方案1:先查询现有实体再更新(最稳妥)
先从数据库查询出待更新的实体,仅修改需要变更的字段,Age字段保留数据库中原有的值,不会触发非空校验。
public async Task<string> UpdateUs(User u) { var existUser = await _dbCont.Users.FirstOrDefaultAsync(x => x.Id == u.Id); if (existUser == null) { return "待更新用户不存在"; } // 仅赋值需要更新的字段 existUser.UserName = u.UserName; existUser.Password = u.Password; await _dbCont.SaveChangesAsync(); return "ok"; }
方案2:手动指定更新字段(不需要提前查库)
将实体附加到上下文后,仅标记需要更新的字段为修改状态,Age字段不会被纳入更新范围。
public async Task<string> UpdateUs(User u) { _dbCont.Users.Attach(u); // 仅标记要更新的字段 _dbCont.Entry(u).Property(p => p.UserName).IsModified = true; _dbCont.Entry(u).Property(p => p.Password).IsModified = true; await _dbCont.SaveChangesAsync(); return "ok"; }
注意:该方案要求传入的User对象必须携带正确的Id值,否则无法定位到待更新的数据库行
方案3(可选):如果业务允许Age可空
如果业务上Age字段本身不是必填项,你可以修改实体配置,移除Age的IsRequired(true)配置,同时将数据库中Age字段改为可空即可,不过该方案不符合你当前3个字段必填的初始设定,仅做参考。
内容的提问来源于stack exchange,提问作者Illep
相关产品推荐
相关产品推荐

