AutoMapper技术问题:如何处理目标对象中源对象无对应字段
问题:AutoMapper更新目标对象时保留未映射字段原有值
当使用源对象更新目标对象时,源对象中不存在的字段会被设置为null,导致目标对象原有值丢失。希望实现仅覆盖源对象存在的字段,保留目标对象其他字段的原有值。
示例代码
源对象类
public class SourceObj{ public int Id {get; set; } public string Name {get; set; } public string Value1{get; set; } }
目标对象类
public class TargetObj{ public int Id {get; set; } public string Name {get; set; } public string Value1{get; set; } public string Value2{get; set; } public string Value3{get; set; } }
映射场景
目标对象初始状态:
{ Id: 1, Name: 'name1', Value1: 'value1', Value2: 'value2', Value3: 'value3', }
源对象内容:
{ Id: 1, Name: 'name1', Value1: 'value1Updated' }
默认映射配置:
CreateMap<SourceObj, TargetObj>();
当前结果与期望结果
当前更新后目标对象(不符合预期):
{ Id: 1, Name: 'name1', Value1: 'value1Updated', Value2: null, Value3: null, }
期望结果:
{ Id: 1, Name: 'name1', Value1: 'value1Updated', Value2: 'value2', Value3: 'value3', }
已尝试但无效的配置
CreateMap<SourceObj, TargetObj>(MemberList.Source); CreateMap<SourceObj, TargetObj>(MemberList.None);
解决方案
要保留目标对象未映射字段的原有值,需使用AutoMapper的对象更新重载方法,而非创建新对象的映射方法:
- 保持基础映射配置不变:
CreateMap<SourceObj, TargetObj>();
- 使用传入目标对象实例的
Map重载方法执行更新:
// 初始化已有目标对象 var target = new TargetObj { Id = 1, Name = "name1", Value1 = "value1", Value2 = "value2", Value3 = "value3" }; // 准备源对象 var source = new SourceObj { Id = 1, Name = "name1", Value1 = "value1Updated" }; // 执行更新:仅覆盖源对象存在的字段 Mapper.Map(source, target);
执行后,target的Value2和Value3会保留原有值,不会被设为null。
原理说明
Mapper.Map(source, destination)是专门用于更新已有对象的方法,只会覆盖源对象中存在的字段,未匹配的字段保留目标对象原有值。- 若使用
Mapper.Map<SourceObj, TargetObj>(source),则会创建全新的目标对象,未映射字段会被设为类型默认值(引用类型为null)。 MemberList参数仅用于验证映射的完整性,和字段是否被覆盖无关,因此之前尝试的配置无法解决问题。
内容的提问来源于stack exchange,提问作者Todd Greenwald
相关产品推荐
相关产品推荐

