ZephyrAxis
ZephyrAxis

Reputation: 65

How to map from a DTO with a foreign key into a hierarchy of nested objects

I'm wishing to use AutoMapper in C# .NET Core to map a set of API responses which are implicitly structured by foreign keys to a set of entity objects so I can store in a DB. I'm receiving the following payload from 3 individual endpoints:.

public class CompanyResponse
{
    public int CompanyId { get; set; }
    public string Name { get; set; }
    public string HeadOffice { get; set; }
}

public class FactoryResponse
{
    public int FactoryId { get; set; }
    public string Address { get; set; }
    public int CompanyId { get; set; }
}

public class ProductResponse
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public int FactoryId { get; set; }
}

This is the nested structure I would like to hold them in:

public class Company
{
    public string Name { get; set; }
    public string HeadOffice { get; set; }
    public IEnumerable<Factory> Factories { get; set; }
}

public class Factory
{
    public string Address { get; set; }
    public IEnumerable<Product> Products { get; set; }
}

public class Product
{
    public string Name { get; set; }
}

There is a one to many relationship from Company -> Factory, and Factory -> Product respectively.

Mapping over the properties like "Name", and "HeadOffice" etc is easy, and I have created AutoMapper maps from each DTO to their corresponding object. However I do not know how to deduce the list of child objects from the Id's.

Here are the maps I have so far:

CreateMap<CompanyResponse, Company>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
    .ForMember(dest => dest.HeadOffice, opt => opt.MapFrom(src => src.HeadOffice));

CreateMap<FactoryResponse, Factory>()
    .ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.Address));

CreateMap<ProductResponse, Product>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name));

Any help would be appreciated!

Upvotes: 2

Views: 2078

Answers (1)

ZephyrAxis
ZephyrAxis

Reputation: 65

People have mentioned that AutoMapper has no knowledge of other collections - hence in order to solve my problem I had to create the hierarchy within the response models. I did this by adding an IEnumerable property within each parent to hold their children.

Then I looped over each of the models and added their corresponding children as follows:

var companyResults = await companyEndpointService.GetAllAsync();
var factoryResults = await factoryEndpointService.GetAllAsync();
var productResults = await productEndpointService.GetAllAsync();

foreach (var company in companyResults)
{
    company.Factories = factoryResults
        .Where(factory => factory.CompanyId == company.CompanyId);

    foreach (var factory in company.Factories)
    {
        factory.Products = productResults
            .Where(product => product.FactoryId == factory.FactoryId);
    }
}

After this heirarchy was set up, I was then able to perform a simple map as follows:

_mapper.Map<IEnumerable<CompanyResponse>, IEnumerable<Company>>(companyResults);

All the nested mapping happened automagically, and everything was good to go.

Upvotes: 1

Related Questions