Automapper多对多映射:插入Product时自动同步ProductProviders记录
问题:插入Product时自动插入ProductProviders记录的AutoMapper映射修复
实体与DTO结构
public class Product { public int Id { get; set; } public string Name { get; set; } public ICollection<ProductProviders> ProductProviders { get; set; } = new HashSet<ProductProviders>(); } public class ProductProviders { public int Id { get; set; } public int ProviderId { get; set; } public int ProductId { get; set; } public Provider Provider { get; set; } public Product Product { get; set; } } public class Provider { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } public ICollection<Product> Products { get; set; } = new HashSet<Product>(); } public class ProductDto { public int Id { get; set; } public string Name { get; set; } public List<ProductProvidersDto> Providers { get; set; } } public class ProductProvidersDto { public int Id { get; set; } public int ProviderId { get; set; } public int ProductId { get; set; } public ProviderDto Provider { get; set; } public ProductDto Product { get; set; } } public class ProviderDto { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } public List<ProductDto> Products { get; set; } }
问题场景
插入Product对象到数据库时,希望自动插入对应的ProductProviders表记录。尝试的映射代码如下:
CreateMap<ProductDto, Product>() .ForMember(dest => dest.ProductProviders, opts => opts.MapFrom(r => r.Providers.Select(r => r.Provider.Id).ToList()));
执行时报错“关系不存在”,已知数据库关系配置正确,所有必要信息已提供,需要修复该映射实现需求。
修复方案
你的错误在于把Provider.Id直接映射到了ProductProviders集合,而ProductProviders是实体类型,不是整数集合。正确的做法是将DTO中的Providers映射为ProductProviders实体实例,只需要填充必要的关联字段即可:
方案1:直接构造ProductProviders实例
CreateMap<ProductDto, Product>() .ForMember(dest => dest.ProductProviders, opts => opts.MapFrom(src => src.Providers.Select(p => new ProductProviders { ProviderId = p.ProviderId, // ProductId无需手动设置,EF会在插入Product后自动填充 }) ));
方案2:添加子映射实现复用
如果需要更通用的映射逻辑,可以先定义ProductProvidersDto到ProductProviders的映射,再在主映射中使用:
// 先定义子实体映射,忽略不必要的导航属性避免循环引用 CreateMap<ProductProvidersDto, ProductProviders>() .ForMember(dest => dest.Product, opt => opt.Ignore()) .ForMember(dest => dest.Provider, opt => opt.Ignore()); // 主映射直接关联子集合 CreateMap<ProductDto, Product>() .ForMember(dest => dest.ProductProviders, opts => opts.MapFrom(src => src.Providers));
关键注意点
- 插入Product时,EF Core会自动处理
ProductId的赋值,无需手动设置 - 若Provider是数据库中已存在的记录,仅需设置
ProviderId即可,不需要完整的Provider实体 - 必须忽略DTO与实体间的循环导航属性,避免映射时出现无限递归问题
内容的提问来源于stack exchange,提问作者predefined_
相关产品推荐
相关产品推荐

