AutoMapper反向映射时集合属性Incidences被置空的问题排查
解决AutoMapper更新集合时Incidences字段被置null的问题
问题原因
核心问题在于AutoMapper默认会替换整个集合而非更新现有实体:执行_mapper.Map(model, item)时,Item.Translations集合会被清空并重新创建ItemTr实例,新实例的Incidences字段因ItemTrView无对应值被设为null,直接覆盖了原有实体的Incidences值。单独给ItemTr映射添加.ForMember(x => x.Incidences, o => o.Ignore())无效,因为AutoMapper是创建新实例而非更新现有实例。
解决方案
需要从两方面配置映射,确保集合更新时保留现有ItemTr实例的Incidences值:
1. 配置ItemTrView到ItemTr的反向映射,保留目标字段值
修改ItemTr的双向映射,明确让Incidences字段使用目标实体的原有值,而非从源模型赋值:
CreateMap<ItemTr, ItemTrView>(MemberList.Source) .ReverseMap() .ForMember(dest => dest.Incidences, opt => opt.UseDestinationValue());
UseDestinationValue()会告诉AutoMapper:更新时直接保留目标实体中Incidences的现有值,忽略源模型(ItemTrView)无对应字段的影响。
2. 配置ItemView到Item的映射,更新集合内现有实体而非替换集合
默认情况下AutoMapper会替换整个Translations集合,需要改为匹配现有实体并更新(假设ItemTr有唯一标识字段Id用于匹配):
CreateMap<Item, ItemView>(MemberList.Source) .ReverseMap() .ForMember(dest => dest.Translations, opt => opt.MapFrom((src, dest, _, context) => src.Translations.Select(srcTr => { // 从目标集合中找到对应Id的现有ItemTr实例 var existingTr = dest.Translations.FirstOrDefault(t => t.Id == srcTr.Id); // 若存在则更新现有实例,不存在则创建新实例 return existingTr != null ? context.Mapper.Map(srcTr, existingTr) : context.Mapper.Map<ItemTr>(srcTr); })));
验证效果
配置完成后,执行_mapper.Map(model, item)时:
Item的原有属性会被保留(遵循MemberList.Source的反向映射规则)Translations集合中的现有ItemTr实例会被正常更新(Summary、Report字段生效)Incidences字段会保留原有值,不会被置为null
内容的提问来源于stack exchange,提问作者John Mathison
相关产品推荐
相关产品推荐

