4

I've seen examples where you can use AutoMapper to combine data from multiple sources to one source.

My question is how can I accomplish this when I am working with lists of data?

EDIT: In my example the List(Person) will map to a List(PersonCompany), however the mapping for the List(Company) to List(PersonCompany) does not map.

EDIT 2: Changed mapper to update the model, however the company mapping is now the only data being mapped.

Say I have the following classes:

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string PhNo { get; set; }
}
public class Company
{
    public int PersonID { get; set; }
    public int EmpNo { get; set; }
    public string Title { get; set; }
}

public class PersonCompany
{
    public string Name { get; set; }
    public string PhNo { get; set; }

    public int EmpNo { get; set; }
    public string Title { get; set; }

    public int ID { get; set; }
}

Now this simple example works...

    // This is a simple example using AutoMapper to map 2 source objects into one destination object.
    var personMapConfig = new MapperConfiguration(c =>
        c.CreateMap<Person, PersonCompany>()
        .ForMember(x => x.Name, y => y.MapFrom(a => a.Name))
        .ForMember(x => x.PhNo, y => y.MapFrom(a => a.PhNo))
        .ForMember(x => x.ID, y => y.MapFrom(a => a.ID))
        );

    var companyMapConfig = new MapperConfiguration(c =>
    c.CreateMap<Company, PersonCompany>()
    .ForMember(d => d.EmpNo, opt => opt.MapFrom(s => s.EmpNo))
    .ForMember(d => d.Title, opt => opt.MapFrom(s => s.Title))
    );

    var person = new Person { ID=1, Name = "PersonName", PhNo = "212-000-0000" };            
    var company = new Company { PersonID = 1, Title = "Associate Director", EmpNo = 10001 };


    var model = personMapConfig.CreateMapper().Map<Person, PersonCompany>(person);
    companyMapConfig.CreateMapper().Map<Company, PersonCompany>(company, model);

However when I work with lists of data it doesn't.

    var personList = new List<Person> { new Person { ID=1, Name="David Johnson", PhNo="(111) 111-1111"},
                                        new Person { ID=2, Name="Marvin Miller", PhNo="(222) 222-2222"},
                                        new Person { ID=3, Name="Jack Wilson", PhNo="(333) 333-3333"}};

    var companyList = new List<Company> { new Company { EmpNo= 1, PersonID = 1, Title="Director"},
                                        new Company { EmpNo= 2, PersonID = 2, Title="Surgeon"},
                                        new Company { EmpNo= 3, PersonID = 3, Title="Sales"}};

    var personMapConfig = new MapperConfiguration(c =>
        c.CreateMap<Person, PersonCompany>()
        .ForMember(x => x.Name, y => y.MapFrom(a => a.Name))
        .ForMember(x => x.PhNo, y => y.MapFrom(a => a.PhNo))
        .ForMember(x => x.ID, y => y.MapFrom(a => a.ID))
    );

    var companyMapConfig = new MapperConfiguration(c =>
        c.CreateMap<Company, PersonCompany>()
        .ForMember(d => d.EmpNo, opt => opt.MapFrom(s => s.EmpNo))
        .ForMember(d => d.Title, opt => opt.MapFrom(s => s.Title))
    );

    var model = personMapConfig.CreateMapper().Map<List<Person>, List<PersonCompany>>(personList);
    companyMapConfig.CreateMapper().Map<List<Company>, List<PersonCompany>>(companyList, model);
John Doe
  • 3,053
  • 17
  • 48
  • 75
  • and what error do you have? in your code you call `Map, List>(companyList)` but you do not assign the result of it to some variable. – MaKCbIMKo May 24 '16 at 14:17
  • Thanks. I didn't realize I didn't pass the 2nd parameter in. I added another edit. – John Doe May 24 '16 at 14:24
  • You should take a look [here](http://stackoverflow.com/questions/21413273/automapper-convert-from-multiple-sources) and see if it answers your question – mdickin May 24 '16 at 14:30

2 Answers2

2

Your last two lines call .Map<List<Person>, List<PersonCompany>() and .Map<List<Company>, List<PersonCompany>>(). Both these calls return the values you'd expect. The problem is that you are not joining the data. You've only told it how to convert Person -> PersonCompany and Company -> PersonCompany, not how to join the data together.

I question whether you need to use AutoMapper for this at all. The following works:

var personList = new List<Person> { new Person { ID=1, Name="David Johnson", PhNo="(111) 111-1111"},
                                        new Person { ID=2, Name="Marvin Miller", PhNo="(222) 222-2222"},
                                        new Person { ID=3, Name="Jack Wilson", PhNo="(333) 333-3333"}};

var companyList = new List<Company> { new Company { EmpNo= 1, PersonID = 1, Title="Director"},
                                    new Company { EmpNo= 2, PersonID = 2, Title="Surgeon"},
                                    new Company { EmpNo= 3, PersonID = 3, Title="Sales"}};

var personCompanies = companyList.Join(personList, m => m.PersonID, m => m.ID, (c, p) => new PersonCompany {
    Name = p.Name,
    PhNo = p.PhNo,
    EmpNo = c.EmpNo,
    ID = p.ID,
    Title = c.Title
});
mdickin
  • 2,365
  • 21
  • 27
2
  public static class MapperExtentions
  {
    public static TResult MergeInto<TResult>(this IMapper mapper, object item1, object item2)
    {
        return mapper.Map(item2, mapper.Map<TResult>(item1));
    }

    public static TResult MergeInto<TResult>(this IMapper mapper, params object[] objects)
    {
        var res = mapper.Map<TResult>(objects.First());
        return objects.Skip(1).Aggregate(res, (r, obj) => mapper.Map(obj, r));
    }
  }

   //How to use extentions
  var personList = new List<Person> { new Person { ID=1, Name="David Johnson", PhNo="(111) 111-1111"},
                                    new Person { ID=2, Name="Marvin Miller", PhNo="(222) 222-2222"},
                                    new Person { ID=3, Name="Jack Wilson", PhNo="(333) 333-3333"}};

  var companyList = new List<Company> { new Company { EmpNo= 1, PersonID = 1, Title="Director"},
                                new Company { EmpNo= 2, PersonID = 2, Title="Surgeon"},
                                new Company { EmpNo= 3, PersonID = 3, Title="Sales"}};

var personMapConfig = new MapperConfiguration(c =>
    c.CreateMap<Person, PersonCompany>()
    .ForMember(x => x.Name, y => y.MapFrom(a => a.Name))
    .ForMember(x => x.PhNo, y => y.MapFrom(a => a.PhNo))
    .ForMember(x => x.ID, y => y.MapFrom(a => a.ID))
);

var companyMapConfig = new MapperConfiguration(c =>
    c.CreateMap<Company, PersonCompany>()
    .ForMember(d => d.EmpNo, opt => opt.MapFrom(s => s.EmpNo))
    .ForMember(d => d.Title, opt => opt.MapFrom(s => s.Title))
);

var model = personMapConfig.CreateMapper().Map<List<Person>, List<PersonCompany>>(personList);
companyMapConfig.CreateMapper().Map<List<Company>, List<PersonCompany>>(companyList, model);

    var result = companyList.Join(personList, s => s.PersonID, t => t.ID, (c, p) => _mapper.MergeInto<PersonCompany>(c, p));
Alex
  • 114
  • 5
  • @chevybow I show the way how I map collection data from multiple sources to one source. What not clear? – Alex Jun 26 '19 at 07:14
  • While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. Code-only answers are not always high quality and be confusing to future readers. – chevybow Jun 26 '19 at 14:14