Reputation: 135
Firstly, I am new to Automapper and finding the official documentation poor to say the least.
I am trying to map two complex entities with virtual collections which themselves need to be mapped
Map<IEnumerable<ComplexEntityDb>, IEnumerable<ComplexEntityVM>>
within each row I need to map
Map<IEnumerable<EntityCollectionItemDb>, IEnumerable<EntityCollectionItemVM>>
A very simplified version of the classes:
public class ComplexEntityDb
{
public int Id;
// Multiple properties (14) removed for brevity
public virtual ICollection<EntityCollectionItemDb> CollectionDb { get; set; }
}
public class ComplexEntityVM
{
public int Id;
// Multiple properties (7) removed for brevity
public virtual ICollection<EntityCollectionItemVM> CollectionDb { get; set; }
}
public class EntityCollectionItemDb
{
public int Id;
// Multiple properties (12) removed for brevity
}
public class EntityCollectionItemVM
{
public int Id;
// Multiple properties (6) removed for brevity
}
What is the correct way to do this with EF Core 5.04 on dotnet 5 using AutoMapper 10.1.1 and DI extensions 8.1.1
I have read dozens of articles on this site and there does not seem to be an easy way to do this.
Many thanks in advance for any help much wiser souls can give.
EDIT: (taken from the comment section of @dglozano's answer) -
I am using mapping profile -
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<ComplexEntityDb, ComplexEntityVM>().ReverseMap();
CreateMap<EntityCollectionItemDb, EntityCollectionItemVM>).ReverseMap();
}
}
and IMapper -
private readonly IMapper _mapper;
public CustomService(IMapper mapper)
{
_mapper = mapper;
}
and trying -
return _mapper.Map<IEnumerable<ComplexEntityDb>, IEnumerable<ComplexEntityVM>>(source);
Result: EntityCollectionItemVM
collection is empty.
Upvotes: 0
Views: 704
Reputation: 6607
You just need to define the mappings of each element type, as the documentation for Nested Mappings suggests. You have to tell Automapper how to map ComplexEntityDb -> ComplexEntityVM
and how to map EntityCollectionItemDb -> EntityCollectionItemVM
, and then all the mappings of collections of those items will automatically be supported.
So in your case, a minimal example would look like this:
using System;
using AutoMapper;
using System.Collections.Generic;
public class ComplexEntityDb
{
public ComplexEntityDb(int id)
{
Id = id;
var item1 = new EntityCollectionItemDb();
var item2 = new EntityCollectionItemDb();
item1.Id = id * 1000 + 1;
item2.Id = id * 1000 + 2;
CollectionDb = new List<EntityCollectionItemDb>{item1, item2, };
}
public int Id
{
get;
set;
}
// Multiple properties (14) removed for brevity
public ICollection<EntityCollectionItemDb> CollectionDb
{
get;
set;
}
}
public class ComplexEntityVM
{
public int Id;
// Multiple properties (7) removed for brevity
public ICollection<EntityCollectionItemVM> CollectionDb
{
get;
set;
}
}
public class EntityCollectionItemDb
{
public int Id;
// Multiple properties (12) removed for brevity
}
public class EntityCollectionItemVM
{
public int Id;
// Multiple properties (6) removed for brevity
}
public class Program
{
public static void Main()
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ComplexEntityDb, ComplexEntityVM>();
cfg.CreateMap<EntityCollectionItemDb, EntityCollectionItemVM>();
});
var complexEntity1 = new ComplexEntityDb(1);
var complexEntity2 = new ComplexEntityDb(2);
var complexEntity3 = new ComplexEntityDb(3);
var source = new List<ComplexEntityDb>{complexEntity1, complexEntity2, complexEntity3};
var mapper = config.CreateMapper();
var dest = mapper.Map<IEnumerable<ComplexEntityDb>, IEnumerable<ComplexEntityVM>>(source);
foreach(var parentMapped in dest)
{
Console.WriteLine("Mapped parent Id {0}", parentMapped.Id);
foreach(var childMapped in parentMapped.CollectionDb)
{
Console.WriteLine(" - Mapped child Id {0}", childMapped.Id);
}
Console.WriteLine();
}
}
}
Output:
Mapped parent Id 1
- Mapped child Id 1001
- Mapped child Id 1002
Mapped parent Id 2
- Mapped child Id 2001
- Mapped child Id 2002
Mapped parent Id 3
- Mapped child Id 3001
- Mapped child Id 3002
In a more real scenario, it would be the same idea, but I would create a Profile(s) to define each of the mappings configurations and then use the injected IMapper
to do execute the mapping.
Upvotes: 1