AutoMapper映射ProductDto到Product时string转Brand报错如何解决?
问题根因
- 你需要将
ProductDto中string类型的品牌名字段映射为Product类中的Brand实体对象,但仅配置了正向Brand实体转string的规则,没有配置反向string转Brand实体的映射规则,AutoMapper找不到对应转换逻辑因此抛出错误。 - 你之前写的
ProductDto到Product的映射配置存在字段错误:误将src.Name(ProductDto的产品名称字段)赋值给了Brand属性,而非ProductDto中存储品牌名的src.Brand字段。
解决方案
方案1:仅映射Brand的Name属性(适合新增品牌场景)
直接配置string到Brand的转换规则,同时修正映射字段即可:
// 配置string转Brand实体的规则 CreateMap<string, Brand>() // 若Id为自增主键可忽略,更新场景下请根据业务逻辑调整Id赋值规则 .ForMember(dest => dest.Id, opt => opt.Ignore()) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src)); // 正向映射规则保持不变 CreateMap<Product, ProductDto>() .ForMember(dest => dest.Brand, opt => opt.MapFrom(p => p.Brand.Name)) .ForMember(dest => dest.Categories, opt => opt.MapFrom(p => p.ProductCategories.Select(pc => pc.Category.Name))); // 修正反向映射规则 CreateMap<ProductDto, Product>() // 取ProductDto的Brand字段(品牌名)映射,而非之前的产品名字段 .ForMember(dest => dest.Brand, opt => opt.MapFrom(src => src.Brand)) // 分类映射可参考品牌逻辑自行补充,暂时不需要可忽略 .ForMember(dest => dest.ProductCategories, opt => opt.Ignore());
如果使用ReverseMap简化配置,可以写成:
CreateMap<string, Brand>() .ForMember(dest => dest.Id, opt => opt.Ignore()) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src)); CreateMap<Product, ProductDto>() .ForMember(dest => dest.Brand, opt => opt.MapFrom(p => p.Brand.Name)) .ForMember(dest => dest.Categories, opt => opt.MapFrom(p => p.ProductCategories.Select(pc => pc.Category.Name))) // 生成反向映射规则 .ReverseMap() .ForMember(dest => dest.Brand, opt => opt.MapFrom(src => src.Brand)) .ForMember(dest => dest.ProductCategories, opt => opt.Ignore());
方案2:关联已有品牌实体(业务常用场景)
实际业务中品牌通常是预先维护在数据库中的,你可以通过自定义值解析器实现自动根据品牌名查询/新增品牌实体:
// 自定义品牌解析器 public class BrandResolver : IValueResolver<ProductDto, Product, Brand> { private readonly YourDbContext _dbContext; // 注入你的数据库上下文 public BrandResolver(YourDbContext dbContext) { _dbContext = dbContext; } public Brand Resolve(ProductDto source, Product destination, Brand destMember, ResolutionContext context) { if (string.IsNullOrWhiteSpace(source.Brand)) return null; // 先查询数据库中是否存在对应名称的品牌 var existedBrand = _dbContext.Brands.FirstOrDefault(b => b.Name.Equals(source.Brand, StringComparison.OrdinalIgnoreCase)); if (existedBrand != null) return existedBrand; // 不存在则新增品牌 var newBrand = new Brand { Name = source.Brand }; _dbContext.Brands.Add(newBrand); return newBrand; } }
然后修改映射配置:
CreateMap<ProductDto, Product>() .ForMember(dest => dest.Brand, opt => opt.MapFrom<BrandResolver>()) .ForMember(dest => dest.ProductCategories, opt => opt.Ignore());
记得将BrandResolver注册到你的依赖注入容器中,使用AddAutoMapper注册AutoMapper时会自动扫描并注入解析器。
内容的提问来源于stack exchange,提问作者Shaq
相关产品推荐
相关产品推荐

