如何使用AutoMapper映射C#中Sales与Products的N对N关系?
解决AutoMapper处理Sales与Products多对多关系的映射问题
首先,我看到你遇到的核心问题是DataModels.Sales到Models.Sales的映射中,Product列表无法正确映射,这主要是因为你的映射配置存在冗余错误,加上一些语义命名的小问题,导致AutoMapper无法正确解析映射逻辑。下面一步步帮你修正:
1. 先修正模型的语义命名(可选但重要)
你的Models.Sales里的属性List<Products> Product命名有歧义,建议改成Products,更符合集合的语义,避免后续混淆:
public class Sales { public int SaleId { get; set; } public Clients Client { get; set; } public float TotalPrice { get; set; } public DateTime? Date { get; set; } // 修正属性名 public List<Products> Products { get; set; } }
2. 清理并修正SalesProfiles的映射配置
你的原SalesProfiles里存在错误的映射规则(比如把Sales映射到SalesProducts、Products映射到SalesProducts),这些完全没必要,反而会干扰AutoMapper的解析。下面是修正后的配置:
public class SalesProfiles : Profile { public SalesProfiles() { // 保留SalesProducts实体与模型的双向映射 CreateMap<DataModels.SalesProducts, Models.SalesProducts>().ReverseMap(); // 核心:Sales实体到Sales模型的映射 CreateMap<DataModels.Sales, Models.Sales>() .ForMember(dest => dest.SaleId, opt => opt.MapFrom(src => src.SaleId)) .ForMember(dest => dest.Client, opt => opt.MapFrom(src => src.Client)) .ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.Date)) .ForMember(dest => dest.TotalPrice, opt => opt.MapFrom(src => src.TotalPrice)) // 从SalesProducts集合中提取关联的Product,AutoMapper会自动使用你已配置的Products映射规则 .ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.SalesProducts.Select(sp => sp.Product))); // 如果需要反向映射(从Models.Sales转DataModels.Sales),添加以下配置 CreateMap<Models.Sales, DataModels.Sales>() .ForMember(dest => dest.SaleId, opt => opt.MapFrom(src => src.SaleId)) .ForMember(dest => dest.ClientId, opt => opt.MapFrom(src => src.Client.ClientId)) // 假设Clients模型包含ClientId .ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.Date)) .ForMember(dest => dest.TotalPrice, opt => opt.MapFrom(src => src.TotalPrice)) // 将模型中的Products转换为SalesProducts集合 .ForMember(dest => dest.SalesProducts, opt => opt.MapFrom(src => src.Products.Select(p => new DataModels.SalesProducts { ProductId = p.ProductId, SaleId = src.SaleId, Quantity = 1 // 这里注意:如果你的模型需要传递数量,得在Models.Sales里添加对应的字段,比如在Products模型里加Quantity,或者改用List<Models.SalesProducts> }) )); } }
3. 确保AutoMapper正确注册所有Profile
在你的项目启动配置中(比如ASP.NET Core的Program.cs或Startup.cs),要确保同时注册SalesProfiles和ProductsProfiles,这样AutoMapper才能找到所有映射规则:
// ASP.NET Core 6+ 示例 builder.Services.AddAutoMapper(typeof(SalesProfiles), typeof(ProductsProfiles));
4. 查询数据时确保加载关联实体
如果你的EF Core查询没有加载SalesProducts和关联的Product,会导致src.SalesProducts为null,映射时出现空引用异常。查询时要使用Include和ThenInclude:
var sale = await _context.Sales .Include(s => s.Client) .Include(s => s.SalesProducts) .ThenInclude(sp => sp.Product) // 加载SalesProducts关联的Product .FirstOrDefaultAsync(s => s.SaleId == saleId); // 执行映射 var saleModel = _mapper.Map<Models.Sales>(sale);
问题根源总结
- 原配置中多余的
Sales→SalesProducts、Products→SalesProducts映射规则,干扰了AutoMapper的正常解析 - 模型属性命名歧义(
Product作为集合名)容易引发逻辑混淆 - 若未正确加载EF Core的关联实体,会导致映射时数据源为空
内容的提问来源于stack exchange,提问作者João Silva
相关产品推荐
相关产品推荐

