如何让AutoMapper处理源属性存在无效ID(无对应实体)的映射问题?
如何让AutoMapper处理源属性存在无效ID(无对应实体)的映射问题?
看起来你碰到的是AutoMapper映射时,源对象里的Product属性虽然不是null,但其实是个绑定了无效ID的实体(数据库里有ID记录,但找不到对应实体)导致的映射失败问题,我来帮你梳理下可行的解决方向:
先搞清楚为什么之前的配置没用
你之前加的AllowNullDestinationValues = true只能解决源属性为null时允许目标属性设为null的场景,但你的情况是源Product本身不是null——只是这个实体是无效的(比如是EF里未加载的幽灵实体,或者字段不完整),AutoMapper还是会尝试去映射这个无效对象,进而触发报错,所以这个配置帮不上忙。
几个可行的解决办法
1. 映射前提前过滤无效的Product
在执行映射操作之前,先检查源对象的Product是否有效(比如根据ID去数据库验证是否存在),如果无效就把它设为null,这样AutoMapper就会自动把目标的Product设为null(不需要额外配置):
// 先自定义一个验证Product有效性的方法 private bool IsProductValid(int productId) { // 这里写你的验证逻辑,比如查数据库确认ID存在 return _productRepository.Exists(productId); } // 映射前处理源对象 if (customerLocation.Product != null && !IsProductValid(customerLocation.Product.Id)) { customerLocation.Product = null; } // 再执行映射 try { UiLocation uiLocation = _mapper.Map<UiLocation>(customerLocation); } catch (Exception ex1) { _logger.Error($"An exception happened .... Exception message=[{ex1.Message}]"); }
2. 给Product类型写自定义映射规则
如果你不想修改源对象,可以直接给源Product类型和目标Product类型创建自定义转换逻辑,在映射时判断源是否有效,无效就返回null或者默认对象:
var locationConfiguration = new MapperConfiguration(cfg => { // 先定义Product类型的自定义映射 cfg.CreateMap<CustomerProduct, UiProduct>() // 替换成你的实际Product类型 .ConvertUsing((sourceProduct, destinationProduct) => { // 验证源Product是否有效 if (sourceProduct == null || !IsProductValid(sourceProduct.Id)) { return null; // 或者返回new UiProduct()作为默认值 } // 正常映射属性 return new UiProduct { Id = sourceProduct.Id, Name = sourceProduct.Name, // 其他需要映射的属性 }; }); // 再定义CustomerLocation到UiLocation的映射 cfg.CreateMap<CustomerLocation, UiLocation>(); });
3. 在父类映射里给Product属性加条件判断
直接在CustomerLocation到UiLocation的映射配置中,给Product属性设置映射条件,只有当源Product有效时才执行映射,否则跳过:
var locationConfiguration = new MapperConfiguration(cfg => { cfg.CreateMap<CustomerLocation, UiLocation>() .ForMember(dest => dest.Product, opt => { // 设置映射条件:只有源Product有效时才映射 opt.Condition(src => src.Product != null && IsProductValid(src.Product.Id)); // 条件不满足时直接设为null opt.MapFrom(src => src.Product != null && IsProductValid(src.Product.Id) ? src.Product : null); }); });
这些方法都能解决你遇到的问题,你可以根据自己的代码结构选择最适合的方式~
备注:内容来源于stack exchange,提问作者Dominique
相关产品推荐
相关产品推荐

