You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:31:31