3

I have a flattened DTO which I need to map to a Parent with Children relationship. I'd like to do this via AutoMapper as I'm using it in other places and it works great. I've seen examples of mapping a Parent and Child but not when the Child is a collection and the source is a flattened DTO. I've created some classes that I can use for getting the configuration correct. Below are my sample classes:

public class Parent
{
    public int ParentId { get; set; }
    public string ParentName { get; set; }

    public List<Child> Children { get; set; }
}
public class Child
{
    public int ChildId { get; set; }
    public string ChildName { get; set; }
}
public class ParentChildDTO
{
    public int ParentId { get; set; }
    public string ParentName { get; set; }
    public int ChildId { get; set; }
    public string ChildName { get; set; }
}

I'm performing the mapper initialization on startup. I'm not getting any errors until I try to perform the mapping. Below is my mapper initialization code. I've kept in the commented out line to show the other way that I've tried to accomplish this:

AutoMapper.Mapper.Initialize(cfg =>
            {
                cfg.CreateMap<ParentChildDTO, Child>();
                cfg.CreateMap<ParentChildDTO, Parent>()
                    .ForMember(dest => dest.Children, opt => opt.MapFrom(src => src));
                    //.ForMember(dest => dest.Children, opt => opt.MapFrom(src => new Child { ChildId = src.ChildId, ChildName = src.ChildName }));               

            });

Below is my code that I'm using for trying to perform the mapping configuration:

ParentChildDTO parentChildDTO = new ParentChildDTO { ParentId = 1, ParentName = "Parent Name", ChildId = 2, ChildName = "Child Name" };
Parent parent = AutoMapper.Mapper.Map<ParentChildDTO, Parent>(parentChildDTO);

List<LienActivity> mapTest = AutoMapper.Mapper.Map<List<BaseActivityUploadDTO>, List<LienActivity>>(request.Activities);

I've considered using a Custom Value Resolver, but was hoping to avoid the complexity and extra code if what I'm doing is possible with the correct configuration.

Here's the error that I get with the above code:

Error mapping types.

Mapping types: ParentChildDTO -> Parent

Type Map configuration: ParentChildDTO -> Parent

Property: Children

Billy Rudasill
  • 105
  • 2
  • 11
  • im a little confused how you flatten the relationship into a single dimension when parent has N number of children. i suppose flattening could use the first child and in reverse could always create a list of children with length one? is this what you are trying to achieve? – Rob S. Mar 26 '18 at 19:39
  • Yes that's what I'm trying to achieve. Basically, the scenario is an excel spreadsheet with each row mapping to a DTO. For an upload, there will only ever be one child in this scenario. – Billy Rudasill Mar 26 '18 at 19:44

2 Answers2

3

Here is another option where you define custom mapping just for the Children property.

Mapper.Initialize(cfg =>
{
   cfg.CreateMap<ParentChildDTO, Parent>()
      .ForMember(d => d.Children, 
         opt => opt.MapFrom(src => new List<Child>() { new Child() { ChildId = src.ChildId, ChildName = src.ChildName } }));
});
Aleš Doganoc
  • 11,568
  • 24
  • 40
0

Given what you are going to use this for based on your comments - the below configuration should do the job (parent properties are resolved by default AutoMapper conventions so no need to explicitly map):

        AutoMapper.Mapper.Initialize(cfg =>
        {
            cfg.CreateMap<ParentChildDTO, Parent>()
                .ConstructUsing(item => new Parent
                {
                    Children = new List<Child>
                    {
                        new Child
                        {
                            ChildId = item.ChildId,
                            ChildName = item.ChildName
                        }
                    }
                });
        });
Vidmantas Blazevicius
  • 4,652
  • 2
  • 11
  • 30
  • This solution also worked. Ultimately, I ended up using the other solution so I marked it as the answer. Thank you for your response! – Billy Rudasill Mar 26 '18 at 20:41