简体   繁体   English

AutoMapper用EF映射ICollection

[英]AutoMapper mapping ICollection with EF

I'm trying to map nested ICollection of one of my models to existing Dto, but I'm struggling to Map it properly with AutoMapper 我正在尝试将我的模型之一的嵌套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: 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; }
}

My maps looks as follows as I'm struggling to properly set "ForMemeber" method(s): 我正在努力设置“ ForMemeber”方法时,我的地图如下所示:

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

Any help much appropriated! 任何帮助都非常合适! Thanks 谢谢

EDIT: 编辑:

This is how I'm getting data: 这就是我获取数据的方式:

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();

First, you must do add CreateMap<IngredientComposition, Composition>(); 首先,您必须添加CreateMap<IngredientComposition, Composition>(); and after doing this you must do change your Linq Query. 然后,您必须更改Linq查询。 You can use AutoMapper.EF6 您可以使用AutoMapper.EF6

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

after use this you donot need use Select . 使用完之后,您不需要使用Select

note: donot forget add _mapper.ConfigurationProvider in ProjectToList 注意: _mapper.ConfigurationProvider忘记在ProjectToList添加_mapper.ConfigurationProvider

ProjectToList<IngredientDto>(_mapper.ConfigurationProvider);

if you don't set it to get this Exception: 如果未将其设置为获取此异常:

Mapper not initialized. 映射器未初始化。 Call Initialize with Appropriate configuration. 调用“使用适当的配置初始化”。 If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance. 如果您尝试通过容器或其他方式使用mapper实例,请确保没有对静态Mapper.Map方法的任何调用,并且如果您使用的是ProjectTo或UseAsDataSource扩展方法,请确保传递适当的IConfigurationProvider实例。

more detail . 更多细节

Update: your properties must have the same name.if you change Dto property Ingredients to IngredientComposition don't need use ForMember . 更新:您的属性必须具有相同的名称。如果将Dto属性更改为IngredientsIngredientComposition则不需要使用ForMember

Actually this worked for me: 实际上,这对我有用:

Query: 查询:

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

Maps: First of All as you suggested, internal collection mapping then main objects mapping + ForMember which worked once internal objects were mapped 映射:首先,正如您所建议的那样,内部集合映射然后是主要对象映射+ ForMember,一旦内部对象被映射,它便起作用

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

Thanks for all help! 感谢所有帮助!

If you make a map for the child DTO, Automapper is smart enough to figure it out without the ForMember : 如果为子DTO绘制地图,则ForMember足够聪明,可以在没有ForMember情况下ForMember

CreateMap<IngredientComposition , Composition>()
    .ReverseMap();  //Reverse map tells AM to go both ways

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

// CreateMap<IngredientDto, Ingredient>();  ** Not needed with ReverseMap()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM