AutoMapper两种Map调用的核心区别及PATCH接口失效原因解析
为什么修改AutoMapper调用后PATCH接口失效?
问题场景
原始可正常工作的PATCH接口代码:
[HttpPatch("{id}")] public async Task<IActionResult> UpdateCity(int id, [FromBody] JsonPatchDocument<CityUpdateDto> patchDoc) { var cityFromRepo = await _citiesRepository.GetCityById(id); var cityToPatch = _mapper.Map<CityUpdateDto>(cityFromRepo); Action<JsonPatchError> errorAction = error => { ModelState.AddModelError(error.Operation.path, error.ErrorMessage);}; patchDoc.ApplyTo(cityToPatch, errorAction); // 有效代码:将修改后的DTO映射回已跟踪的实体 _mapper.Map(cityToPatch, cityFromRepo); await _citiesRepository.SaveChangesAsync(); return Ok("Done update"); }
修改后失效的代码:
[HttpPatch("{id}")] public async Task<IActionResult> UpdateCity(int id, [FromBody] JsonPatchDocument<CityUpdateDto> patchDoc) { var cityFromRepo = await _citiesRepository.GetCityById(id); var cityToPatch = _mapper.Map<CityUpdateDto>(cityFromRepo); Action<JsonPatchError> errorAction = error => { ModelState.AddModelError(error.Operation.path, error.ErrorMessage);}; patchDoc.ApplyTo(cityToPatch, errorAction); // 无效代码:仅创建新实体,未更新原有跟踪实体 _mapper.Map<City>(cityToPatch); await _citiesRepository.SaveChangesAsync(); return Ok("Done update"); }
核心疑问:两种AutoMapper调用方式的差异是什么,为何修改后接口无法更新数据?
两种AutoMapper调用的本质区别
1. _mapper.Map(cityToPatch, cityFromRepo)(Map(TSource source, TDestination destination))
这是更新已有目标对象的调用方式:
- 第一个参数是源数据对象(已经被Patch修改过的
CityUpdateDto),第二个参数是已经存在的目标对象(从数据库获取的City实体,且处于EF Core上下文的跟踪状态) - AutoMapper会遍历源对象的属性,将对应值复制到目标对象的同名属性上
- 由于目标对象
cityFromRepo是EF Core正在跟踪的实体,属性的变更会被EF Core捕获,当调用SaveChangesAsync()时,EF Core会自动生成SQL UPDATE语句,将变更同步到数据库
2. _mapper.Map<City>(cityToPatch)(Map<TDestination>(TSource source))
这是创建全新目标对象的调用方式:
- 该调用会以
cityToPatch为数据源,创建一个全新的City类实例 - 这个新创建的
City对象完全独立于从数据库获取的cityFromRepo,也没有被EF Core上下文跟踪 - 调用
SaveChangesAsync()时,EF Core只会处理它正在跟踪的实体(也就是原来的cityFromRepo),而这个新对象的属性变更和原有实体毫无关系,因此数据库不会有任何更新
修改后接口失效的原因
修改后的代码仅通过AutoMapper创建了一个新的City对象,但没有将这个新对象的属性同步到EF Core正在跟踪的cityFromRepo上,也没有把新对象附加到EF Core上下文让其被跟踪。EF Core检测不到原有实体cityFromRepo的任何属性变更,所以调用SaveChangesAsync()时不会执行任何数据库更新操作,最终导致PATCH接口无法正常修改数据。
内容的提问来源于stack exchange,提问作者Akash Singh Rawat
相关产品推荐
相关产品推荐

