首页 文章

AutoMapper使用EF映射ICollection

提问于
浏览
1

我正在尝试将我的一个模型的嵌套ICollection映射到现有的Dto,但我正在努力使用AutoMapper正确映射它

Models:

public class Ingredient : BaseEntity<long>
{
    [MaxLength(100)]
    public string Name { get; set; }
    [ForeignKey("Id")]
    public int CustomerId { get; set; }
    public bool IsPackaging { get; set; }
    public virtual ICollection<ProductIngredient> ProductIngredient { get; set; }
    public virtual ICollection<IngredientComposition> IngredientComposition { get; set; }
}

Collection Model:

public class IngredientComposition : BaseEntity<int>
{
    [MaxLength(20)]
    public string Type { get; set; }
    [MaxLength(200)]
    public string Key { get; set; }
    [MaxLength(200)]
    public string Value { get; set; }
}

Dto:

public class IngredientDto
{
    public long Id { get; set; }
    public DateTime CretedOn { get; set; }
    public DateTime UpdatedOn { get; set; }
    public string Name { get; set; }
    public int CustomerId { get; set; }
    public int UsedCount { get; set; }
    public bool IsPackaging { get; set; }
    public IList<Composition> Ingredients { get; set; }
}

public class Composition
{
    public string Type { get; set; }
    public string Key { get; set; }
    public string Value { get; set; }
}

我的 Map 看起来如下,因为我正在努力正确设置“ForMemeber”方法:

CreateMap<Ingredient, IngredientDto>();
CreateMap<IngredientDto, Ingredient>();

任何帮助很多!谢谢

编辑:

这就是我获取数据的方式:

return await _context.Ingredients
                     .Where(i => i.CustomerId ==_userResolverService.GetCustomerId())
                     .Include(i => i.IngredientComposition)
                     .Select(i => _mapper.Map<Ingredient, IngredientDto>(i))
                     .OrderBy(i => i.Name)
                     .ToListAsync();

3 回答

  • 0

    首先,您必须添加 CreateMap<IngredientComposition, Composition>(); ,执行此操作后,您必须更改Linq查询 . 你可以用AutoMapper.EF6

    return _context.Ingredients
                     .Where(i => i.CustomerId ==_userResolverService.GetCustomerId())
                     .Include(i => i.IngredientComposition)
                     .ProjectToList<IngredientDto>();
    

    使用后你不需要使用 Select .

    注意:不要忘了在 ProjectToList 中添加 _mapper.ConfigurationProvider

    ProjectToList<IngredientDto>(_mapper.ConfigurationProvider);
    

    如果你没有设置它来获得此异常:

    Mapper未初始化 . 使用适当的配置调用Initialize . 如果您尝试通过容器或其他方式使用映射器实例,请确保您没有对静态Mapper.Map方法的任何调用,并且如果您使用的是ProjectTo或UseAsDataSource扩展方法,请确保传入适当的IConfigurationProvider实例 .

    更多detail .

    Update: 您的属性必须具有相同的名称 . 如果您将Dto属性 Ingredients 更改为 IngredientComposition ,则不需要使用 ForMember .

  • 1

    实际上这对我有用:

    查询:

    return await _context.Ingredients.Where(i => i.CustomerId == _userResolverService.GetCustomerId())
            .Include(sx=>sx.IngredientComposition)
            .ProjectTo<IngredientDto>()
            .ToListAsync();
    

    Map :首先按照您的建议,内部集合映射然后映射ForMember的主要对象,一旦内部对象被映射就可以工作

    CreateMap<IngredientComposition, Composition>().ReverseMap();
    CreateMap<Ingredient, IngredientDto>().ForMember(d => d.Ingredients, opt=>opt.MapFrom(c=>c.IngredientComposition)).ReverseMap();
    

    谢谢大家的帮助!

  • 3

    如果您为子DTO制作 Map ,Automapper足够聪明,可以在没有 ForMember 的情况下找到它:

    CreateMap<IngredientComposition , Composition>()
        .ReverseMap();  //Reverse map tells AM to go both ways
    
    CreateMap<Ingredient, IngredientDto>()
        .ReverseMap();
    
    // CreateMap<IngredientDto, Ingredient>();  ** Not needed with ReverseMap()
    

相关问题