I'm trying to map entities into a collection through a many to many table using AutoMapper.
My domain model (Entity Framework) looks like this:
public class User
{
public int UserID { get; set; }
public string Name { get; set; }
public IList<UserCompany> UserCompanies { get; set; }
}
public class Company
{
public int CompanyID { get; set; }
public string Name { get; set; }
}
public class UserCompany
{
public int UserCompanyID { get; set; }
public int UserID { get; set; }
public int CompanyID { get; set; }
}
I'm trying to map to a class that looks like this:
public class CompanyDTO
{
public int CompanyID { get; set; }
public string Name { get; set; }
}
public class UserDTO
{
public int UserID { get; set; }
public string Name { get; set; }
public IList<CompanyDTO> Companies { get; set; }
}
My current mapping configuration looks like this:
Mapper.CreateMap<Company, CompanyDTO>(); //works no problem
Mapper.CreateMap<User, UserDTO>()
.ForMember( dto => dto.Companies,
opt => opt.MapFrom(x => Mapper.Map<IList<Company>, IList<CompanyDTO>>(x.UserCompanies.Select( y => y.Company ).ToList())));
Asserting that the configuration is valid returns true, but when I try to actually map a User to a UserDTO, I get: Signature of the body and declaration in a method implementation do not match.
If I use AfterMap and manually move over each Company into the Companies list, it will work, but it seems like I should be able to handle this within create map.
In my query to get a single user from the DB I am including the UserCompany.Company navigation property and I can quickwatch and see that there is being returned.
You don't need to have the explicit map in your mapping configuration. You should be able to do something like:
Mapper.CreateMap<User, UserDTO>()
.ForMember(dto => dto.Companies, opt => opt.MapFrom(x => x.UserCompanies));
You'll also need to define a mapping for UserCompany:
Mapper.CreateMap<UserCompany, CompanyDTO>();
Note that you don't have a CompanyDTO class in your examples so I can't determine the actual mapping configuration.
Update
I presume there is a reason why you need an IList in your User entity rather than simply an IList. Given that, I believe you need a custom resolver: https://github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers
Update 2
I'm glad you have it sorted. For completeness, heres the example should you decide to use a custom ValueResolver with the classes above.
Mapper.CreateMap<Company, CompanyDTO>();
Mapper.CreateMap<User, UserDTO>()
.ForMember(dto => dto.Companies, opt => opt.ResolveUsing<CompanyResolver>());
Mapper.AssertConfigurationIsValid();
Where CompanyResolver is something like
public class CompanyResolver : ValueResolver<User, IList<CompanyDTO>>
{
protected override IList<CompanyDTO> ResolveCore(User source)
{
return source.UserCompanies
.Select(userCompany =>
Mapper.Map<Company, CompanyDTO>(companies.FirstOrDefault(x => x.CompanyID == userCompany.CompanyID)))
.ToList();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With