AutoMapper映射时未忽略Date字段致其变为DateTime.MinValue问题
AutoMapper更新目标实体时保留指定字段原有值失败问题
我尝试将EntityModel映射到Entity实体,同时保留目标实体中某个字段的原有值。我的.NET类定义如下:
class Entity { public string User {get; set;} public DateTime Date {get; set;} } class EntityModel { public string User {get; set;} public DateTime Date {get; set;} }
配置的映射规则如下:
CreateMap<EntityModel, Entity>() .ForMember(f => f.Date, m => m.Ignore());
我期望执行mapper.Map<EntityModel, Entity>(entityModel, entity)时,仅复制User字段的值,同时保留目标实体原有的Date值,但实际运行后目标实体的Date被设置成了DateTime.MinValue(01/01/0001 00:00:00)。我使用的是最新版AutoMapper(12.0.1)。
编辑补充:已复现问题,该问题仅在涉及列表映射时出现——当映射包含子实体列表的对象时,子实体列表中已存在的元素的Date字段会被覆盖为DateTime.MinValue。
问题原因及解决方法
核心原因
AutoMapper处理集合(列表)时,默认会重新创建集合内的子实体实例,而非对已有实例进行更新。即便你配置了忽略Date字段,新创建的子实体实例的Date字段会被初始化为DateTime.MinValue,导致原有值丢失。
解决方案
要保留子实体原有字段值,需配置AutoMapper对集合采用更新已有元素的策略,而非重新创建实例,具体可参考以下几种方式:
方式1:手动映射集合元素,复用目标实例
在父实体的映射配置中,手动将源集合元素映射到目标集合的已有实例:
// 先确保子实体的映射配置正确忽略Date字段 CreateMap<ChildEntityModel, ChildEntity>() .ForMember(dest => dest.Date, opt => opt.Ignore()); // 父实体映射时,遍历目标集合,用源元素更新目标元素 CreateMap<ParentEntityModel, ParentEntity>() .ForMember(dest => dest.ChildEntities, opt => opt.MapFrom((src, dest, _, context) => dest.ChildEntities.Zip(src.ChildEntities, (destChild, srcChild) => context.Mapper.Map(srcChild, destChild))));
方式2:启用引用保留+集合匹配(适用于子实体有唯一标识)
如果子实体有唯一ID字段,可配置AutoMapper根据标识匹配源和目标元素,并保留原有实例:
CreateMap<ChildEntityModel, ChildEntity>() .ForMember(dest => dest.Date, opt => opt.Ignore()) .PreserveReferences(); // 保留对象引用,避免重新创建 CreateMap<ParentEntityModel, ParentEntity>() .ForMember(dest => dest.ChildEntities, opt => opt.MapFrom((src, dest, _, context) => context.Mapper.Map<IEnumerable<ChildEntityModel>, IEnumerable<ChildEntity>>( src.ChildEntities, dest.ChildEntities))) .PreserveReferences();
方式3:禁用集合自动替换
创建Mapper配置时开启AllowNullCollections,避免AutoMapper直接替换整个目标集合:
var config = new MapperConfiguration(cfg => { cfg.AllowNullCollections = true; // 允许目标集合为null,不自动替换 // 其他映射配置 });
内容的提问来源于stack exchange,提问作者Gusky
相关产品推荐
相关产品推荐

