I need to output a list (EntityListDto) to client. This EntityListDto is mapped from two entities:
[AutoMapFrom(typeof(Entity1), typeof(Entity2))] public class EntityListDto : EntityDto { public string PropertyFromEntity1 { get; set; } public string PropertyFromEntity2 { get; set; } }
I made a service:
public EntityListDto GetEntity(int Id)
{
var entity1 = _entityt1Repository
.GetAll()
.Where(w => w.Id == Id);
var entity2 = _entity2Repository
.GetAll()
.Where(w => w.FKId == Id);
var entity = entity1.GroupJoin(entity2, e1 => e1.Id, e2 => e2.FkId, (e1, e2) => new { entity1 = e1, entity2 = e2.FirstOrDefault() }).FirstOrDefault();
return ObjectMapper.Map<EntityListDto>(entity);
}
It throws an exception on the last line:
AutoMapper.AutoMapperMappingException: 'Missing type map configuration or unsupported mapping.'
How should I use ObjectMapper to Map the joined entity?
Thanks,
4 Answer(s)
-
0
Your entity is anonymous type since you GroupJoin with new, so the mapping is unsupported.
Do this:
public EntityListDto GetEntity(int Id) { var entity1 = _entity1Repository.Get(Id); var entity2 = _entity2Repository.FirstOrDefault(w => w.FKId == Id); var dto = ObjectMapper.Map<EntityListDto>(entity1); return ObjectMapper.Map(entity2, dto); }
-
0
Nice and Neat! Thank you very much!!
However, I got two glitches:
I actually want to entity1 LEFT JOIN entity2. Your code seems just working as "inner Join". When I try your code with an empty entity2, it results an empty EntityDto. It should be an EntityDto with values of all PropertyFromEntity1 but null for all PropertyFromEntity2. I reversed the order of mapping and solved it. Is it the correct way?
Another problem is about Id. As convention, both entity1 and entity2 have field "Id". I want to keep entity1.Id as EntityDto.Id and ignore entity2.Id. When I try your code, it returns the EntityDto.Id = entity2.Id, because the last mapping is on the entity2, I think. I surely can reverse the order of mapping in this particular example to solve this issue, but generally, how do I handle if entity1 and entity2 have same name properties?
For example, if I need:
[AutoMapFrom(typeof(Entity1), typeof(Entity2))] public class EntityListDto : EntityDto { public string XYZ { get; set; } // map with Entity1.XYZ, instead of Entity2.XYZ public string ABC { get; set; } // map with Entity2.ABC, instead of Entity1.ABC }
Usually, most of properties can be auto-mapped correctly, but only few of them (such as Id, name, email ...) have this kind of issue when I map joined entities. Can you show me a correct way?
Thanks again!
-
0
When I try your code with an empty entity2, it results an empty EntityDto. It should be an EntityDto with values of all PropertyFromEntity1 but null for all PropertyFromEntity2. I reversed the order of mapping and solved it. Is it the correct way?
Yes, that's AutoMapper behavior for null source. Alternatively, you can add a null-check.
I want to keep entity1.Id as EntityDto.Id and ignore entity2.Id. When I try your code, it returns the EntityDto.Id = entity2.Id, because the last mapping is on the entity2, I think. I surely can reverse the order of mapping in this particular example to solve this issue...
Yes, map the overriding one last.
...but generally, how do I handle if entity1 and entity2 have same name properties?
Create a Profile:
public class EntityListDtoProfile : Profile { public EntityListDtoProfile() { CreateMap<Entity1, EntityListDto>() .ForMember(dest => dest.ABC, opt => opt.Ignore()); // ignore Entity1.ABC CreateMap<Entity2, EntityListDto>() .ForMember(dest => dest.XYZ, opt => opt.Ignore()); // ignore Entity2.XYZ } }
Add profiles by assembly scanning in the PreInitialize method of YourApplicationModule:
Configuration.Modules.AbpAutoMapper().Configurators.Add(cfg => { cfg.AddProfiles(typeof(YourApplicationModule).GetAssembly()); });;
-
0
Excellent!!
I will try this way later when I handle complicated mapping case.
Thanks again!!