ASP.NET Core MVC中AutoMapper映射ICollection及反向映射保存问题
ICollection类型映射失败问题解决
问题原因
AutoMapper默认采用属性名完全匹配规则执行自动映射,你的Car实体中集合属性名为CarDetails,而CarVM中对应集合属性名为CarDetailsVM,二者名称不匹配,因此集合字段无法完成自动映射。
解决办法
有两种可选方案:
方案1:统一属性名(推荐,减少冗余配置)
将CarVM中的集合属性名修改为和实体一致的CarDetails,无需修改映射配置即可完成自动映射:
public class CarVM { public ICollection<CarDetailsVM> CarDetails { get; set; } public string Name{ get; set; } }
方案2:显式配置映射规则
如果不需要修改属性名,可以在映射配置中显式指定字段对应关系:
CreateMap<Car, CarVM>() // 正向映射:实体CarDetails映射到VM的CarDetailsVM .ForMember(dest => dest.CarDetailsVM, opt => opt.MapFrom(src => src.CarDetails)) .ReverseMap() // 反向映射:VM的CarDetailsVM映射到实体的CarDetails .ForMember(dest => dest.CarDetails, opt => opt.MapFrom(src => src.CarDetailsVM)); CreateMap<CarDetails, CarDetailsVM>().ReverseMap();
反向映射代码注意事项
你现有提交的反向映射代码逻辑是正确的,但存在EF Core场景下的集合更新风险:
AutoMapper默认会直接替换整个ICollection集合对象,而不是增量更新现有集合元素,直接保存可能会触发旧子项全量删除再插入的操作,甚至引发外键异常。如果需要支持子集合的增删改操作,建议手动处理子集合变更,优化后代码示例:
[HttpPost] public IActionResult Car(CarVM viewModel) { var carObject = repo.GetData(1); // 映射普通字段 _mapper.Map(viewModel, carObject); // 处理子项更新/新增 foreach (var detailVm in viewModel.CarDetailsVM) { var existingDetail = carObject.CarDetails.FirstOrDefault(d => d.Id == detailVm.Id); if (existingDetail != null) { _mapper.Map(detailVm, existingDetail); } else { var newDetail = _mapper.Map<CarDetails>(detailVm); carObject.CarDetails.Add(newDetail); } } // 处理被删除的子项 var submitIds = viewModel.CarDetailsVM.Select(d => d.Id).ToList(); var toDeleteDetails = carObject.CarDetails.Where(d => !submitIds.Contains(d.Id)).ToList(); foreach (var del in toDeleteDetails) { carObject.CarDetails.Remove(del); } repo.Save(carObject); return Ok(); }
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

