数据传递正确但记录未写入SQL Server?ASP.NET WEB API与Angular问题
问题原因及排查修复方案
核心故障原因
你现在的核心问题是完全没有处理CreateBranchAddress方法的返回结果,就算这个方法内部触发了校验失败、数据库报错返回BadRequest,外层的CreateBranch方法也会直接返回Ok,你自然感知不到错误。
其余常见的潜在故障点如下:
CreateBranchAddress方法中的ModelState校验完全无效:ModelState是当前Controller实例的属性,只会校验接口入口的[FromBody] BranchesVM参数,你手动构造的BranchAddress实体根本不会被ModelState校验,只要入参BranchesVM校验通过,这里的ModelState.IsValid永远为true,完全起不到校验作用,甚至如果之前的入参校验有残留错误,还会导致这里误判不执行插入逻辑。- 实体配置问题:检查
BranchAddress的实体定义和EF映射配置,是否存在BranchId外键关联配置错误、必填字段未赋值、字段长度超出限制等问题,这类错误会触发EF异常,但因为你没有捕获CreateBranchAddress的返回值,所以看不到错误。 - 冗余逻辑干扰:你在插入
Branch后调用OrderByDescending查最新Branch的逻辑完全多余,EF在自增主键实体调用SaveChanges后,会自动把生成的主键值回写到实体上,直接用branch.BranchId即可,多出来的查询如果在高并发场景下还可能拿到别的请求插入的BranchID,导致外键关联错误。
修复方案
方案1:直接合并逻辑(推荐,避免跨方法问题)
把CreateBranchAddress的逻辑直接合并到CreateBranch中,用事务保证两个操作的原子性,要么同时成功要么同时失败:
[HttpPost] [Route("CreateBranch")] public ActionResult CreateBranch([FromBody] BranchesVM newBranch) { if (!ModelState.IsValid) { return BadRequest(ModelState); } // 开启事务保证原子性 using var transaction = db.Database.BeginTransaction(); try { var branch = new Branch { BranchName = newBranch.branch.BranchName, BranchContactNumber = newBranch.branch.BranchContactNumber, BranchEmailAddress = newBranch.branch.BranchEmailAddress, BranchImage = newBranch.branch.BranchImage, BranchStatus = true }; db.Branch.Add(branch); db.SaveChanges(); var branchAddress = new BranchAddress { BranchStreetName = newBranch.address.BranchStreetName, BranchSuburb = newBranch.address.BranchSuburb, BranchCity = newBranch.address.BranchCity, BranchProvince = newBranch.address.BranchProvince, BranchCountry = newBranch.address.BranchCountry, BranchZip = newBranch.address.BranchZip, BranchDate = DateTime.Now, BranchLate = newBranch.address.BranchLate, BranchLng = newBranch.address.BranchLng, // 直接用已经赋值的BranchId即可 BranchId = branch.BranchId }; db.BranchAddress.Add(branchAddress); db.SaveChanges(); // 两个操作都成功再提交事务 transaction.Commit(); return Ok(); } catch (Exception e) { // 任意步骤失败就回滚 transaction.Rollback(); return BadRequest(e.Message); } }
方案2:调整拆分方法的逻辑
如果一定要拆分为两个方法,把CreateBranchAddress改为私有方法,移除无效的ModelState校验,直接抛出异常或者返回执行结果,外层判断后再返回:
private bool CreateBranchAddress(BranchAddress newBranchAddress) { try { db.BranchAddress.Add(newBranchAddress); return db.SaveChanges() > 0; } catch { return false; } }
外层调用时判断返回结果:
var addressSaved = CreateBranchAddress(branchAddress); if(!addressSaved) { // 可以在这里回滚之前插入的Branch,或者返回错误 return BadRequest("地址保存失败"); } return Ok();
临时排查手段
如果修复后还是有问题,在CreateBranchAddress的SaveChanges行打断点,查看以下信息:
newBranchAddress的所有属性值是否符合预期,尤其是BranchId是否有值db.SaveChanges()的返回值,大于0代表确实有行被插入,等于0代表没有执行插入操作- 查看
db.ChangeTracker.Entries<BranchAddress>()中对应实体的State是否为Added
内容的提问来源于stack exchange,提问作者SeventhWarhawk
相关产品推荐
相关产品推荐

