AutoMapper使用EF映射ICollection

时间:2017-08-21 18:00:56

标签: c# entity-framework .net-core automapper

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

型号:

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; }
}

收藏模型:

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; }
}

我的地图如下所示,因为我正在努力正确设置“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 :(得分:3)

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

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

使用后你不需要使用Select

注意:不要忘记在_mapper.ConfigurationProvider

中添加ProjectToList
ProjectToList<IngredientDto>(_mapper.ConfigurationProvider);

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

  

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

更多detail

更新:您的媒体资源必须具有相同的名称。如果您将Dto属性Ingredients更改为IngredientComposition,则无需使用ForMember

答案 1 :(得分:1)

实际上这对我有用:

查询:

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

图: 首先,如您所建议的那样,内部集合映射然后主要对象映射+ ForMember,一旦内部对象被映射就可以工作

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

感谢您的帮助!

答案 2 :(得分:0)

如果您为儿童DTO制作地图,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()