C# AutoMapper忽略子对象属性异常:Item的CreateDate被重置为默认值
解决AutoMapper更新子对象时重置CreateDate的问题
问题根源
你遇到的问题核心是:AutoMapper映射子对象ItemInput到ItemEntity时,没配置忽略CreateDate属性,而你的ItemInput要么没定义这个属性,要么请求里没传该值,导致映射时把数据库原有实体的CreateDate覆盖成了默认值。父对象WarehouseEntity的忽略规则生效,是因为你明确在映射配置里指定了忽略它的LocationId和CreateDate,但子对象的对应规则没跟上。
解决方案
1. 给子对象添加映射忽略规则
在AutoMapper的Profile配置中,单独为ItemInput到ItemEntity的映射添加忽略CreateDate的规则,同时保留父对象的正确配置。示例代码:
public class WarehouseProfile : Profile { public WarehouseProfile() { // 父对象映射:忽略无需更新的字段 CreateMap<WarehouseInput, WarehouseEntity>() .ForMember(dest => dest.LocationId, opt => opt.Ignore()) .ForMember(dest => dest.CreateDate, opt => opt.Ignore()); // 子对象映射:忽略CreateDate,只更新传入的属性(比如IsActive) CreateMap<ItemInput, ItemEntity>() .ForMember(dest => dest.CreateDate, opt => opt.Ignore()); } }
2. 基于数据库原有实体做更新
更新操作时,必须先从数据库查询出完整的WarehouseEntity(包含关联的ItemEntity列表),再把WarehouseInput的数据映射到这个已存在的实体上,而非新建实体。这样AutoMapper只会覆盖你传入的属性值,忽略的字段会保留数据库原有值。示例代码:
public async Task<IActionResult> UpdateWarehouse(int id, WarehouseInput input) { // 从数据库获取已存在的仓库实体(包含关联的商品) var existingWarehouse = await _dbContext.Warehouses .Include(w => w.Items) .FirstOrDefaultAsync(w => w.Id == id); if (existingWarehouse == null) { return NotFound(); } // 将输入数据映射到原有实体上 _mapper.Map(input, existingWarehouse); // 保存更改到数据库 await _dbContext.SaveChangesAsync(); return Ok(existingWarehouse); }
3. 可选:配置条件映射(适配部分更新场景)
如果需要更灵活的规则——只有当ItemInput里的属性有明确有效值时才映射(避免误覆盖原有值),可以添加条件映射:
CreateMap<ItemInput, ItemEntity>() .ForMember(dest => dest.CreateDate, opt => opt.Ignore()) // 示例:仅当IsActive有明确值时才更新(可根据需求调整) .ForMember(dest => dest.IsActive, opt => opt.Condition(src => src.IsActive.HasValue));
验证要点
- 检查
ItemInput类:如果不需要通过输入更新CreateDate,直接删掉该类里的CreateDate属性,减少出错可能。 - 测试Swagger请求:仅传入
Item的IsActive为false,映射后查看existingWarehouse.Items的CreateDate是否保留数据库原有值,IsActive是否成功改为false。
内容的提问来源于stack exchange,提问作者Berker
相关产品推荐
相关产品推荐

