Automapper v6.2.2更新仅映射字段:未映射字段被置空求助
解决Automapper更新时未映射字段被置为null的问题
我刚接触Automapper时也踩过一模一样的坑,你遇到的核心问题其实是创建了全新的目标对象,而非将源数据映射到已从数据库加载的现有实体上,这才导致未映射字段被覆盖成null。
问题根源分析
当你执行Mapper.Map<TDomain>(entity)时,Automapper会生成一个全新的PT_Registration实例——那些没配置映射的属性(比如EMail_VC和Comments_VC)会被初始化为默认值null。接着你把这个新对象的状态设为EntityState.Modified,EF会认为所有属性都需要更新,自然就把数据库里的原有值覆盖成null了。
之前你尝试的ForAllOtherMembers(opt => opt.Ignore())、MemberList配置等之所以没用,是因为这些配置只控制映射过程中是否覆盖属性,但你是在创建新对象,未映射属性本来就是null,根本没有“原有值”可以保留。
可行解决方案
正确的做法是:先从数据库加载要更新的现有实体,再将源对象的属性映射到这个现有实体上,而非创建新对象。
修改Repository.cs代码:
// 1. 先从数据库获取要更新的现有实体(替换成你的查询逻辑,比如用ID查找) var existingRegistration = DatabaseContext.PT_Registration.Find(registrationId); // 2. 将源对象的属性映射到现有实体,而非创建新对象 Mapper.Map(entity, existingRegistration); // 3. 无需手动设置EntityState.Modified! // EF的变更追踪会自动识别哪些属性被修改,只更新变化的字段 // 如果你的上下文关闭了自动追踪,才需要手动标记,但通常不需要这一步 // DatabaseContext.Entry(existingRegistration).State = EntityState.Modified;
确保映射配置正确:
你的InvoiceLineMapping.cs里必须加上ForAllOtherMembers(opt => opt.Ignore()),确保Automapper不会覆盖未配置映射的属性:
public static void Map(IProfileExpression profile) { profile.CreateMap<Registration, PT_Registration>() .ForMember(d => d.Name_VC, map => map.MapFrom(s => s.Name)) .ForMember(d => d.UserName_VC, map => map.MapFrom(s => s.Username)) .ForMember(d => d.Mobile_VC, map => map.MapFrom(s => s.Mobile)) .ForAllOtherMembers(opt => opt.Ignore()); // 关键:忽略所有未配置的成员 }
额外说明
MemberList.Source/Destination是用来做映射验证的(比如检查是否有未映射的源/目标成员),和属性覆盖问题无关,不用在这个场景里纠结。ReverseMap()只是创建反向映射(从PT_Registration到Registration),和当前更新逻辑无关。- 不要尝试“移除目标对象的null值”,这是绕远路,Automapper+EF的正确姿势就是映射到现有实体。
这样修改后,EMail_VC和Comments_VC会保留数据库里的原有值,只有你配置的三个字段会被更新。
内容的提问来源于stack exchange,提问作者gkrishy
相关产品推荐
相关产品推荐

