I'm struggling to figure out how to correctly map an EF core object with inheritance to a DTO using AutoMapper. The correct result I'm looking for is a DTO that has one Training AND ALL the Employees that are registered for it:
Here are the three classes:
public class Training
{
public Guid Id { get; set; }
public string Host { get; set; }
public string Name { get; set; }
public ICollection<EmployeeTraining> EmployeeTrainings { get; }
}
public class Employee
{
public Guid Id { get; set; }
public string Designation { get; set; }
public ICollection<EmployeeTraining> EmployeeTrainings { get; }
}
public class EmployeeTraining
{
public Guid EmployeeId {get; set;}
public Employee Employee { get; set; }
public Guid TrainingId { get; set; }
public Training Training{ get; set; }
}
public class TrainingDTO
{
public string Host { get; set; }
public string Name { get; set; }
public ICollection<EmployeeTraining> EmployeeTrainings { get; }
}
AutoMapper Profile:
public class TrainingProfile: Profile
{
public TrainingProfile()
{
CreateMap<Training, TrainingDto>()
.ForMember(entity => entity.EmployeeTrainings, opt => opt.MapFrom(model => model));
CreateMap<TrainingDto, Training>();
}
}
The code compiles, but when run I get:
[2021-05-03T21:21:49.201Z] Exception: Error mapping types.
[2021-05-03T21:21:49.203Z] Mapping types:
[2021-05-03T21:21:49.204Z] Training -> TrainingDto
[2021-05-03T21:21:49.208Z] AzITSSMaster.API.Entities.Training -> AzITSSMaster.API.Models.TrainingDto
[2021-05-03T21:21:49.209Z] Type Map configuration:
[2021-05-03T21:21:49.209Z] Training -> TrainingDto
[2021-05-03T21:21:49.211Z] AzITSSMaster.API.Entities.Training -> AzITSSMaster.API.Models.TrainingDto
[2021-05-03T21:21:49.212Z] Destination Member:
[2021-05-03T21:21:49.212Z] EmployeeTrainings
Test
[Fact]
public void Test1()
{
Guid trainingOneGuid = new Guid("5b1c2b4e48c7402a80c3cc796ad49c6b");
Guid trainingTwoGuid = new Guid("d8663e5f74944f8187396e0de1bea7ee");
Guid employeeOneGuid = new Guid("5b1c2b4d48c7402a80c3cc796ad49c6b");
Guid employeeTwoGuid = new Guid("d8663e5e74944f8187396e0de1bea7ee");
//Create In Memory Database
var options = new DbContextOptionsBuilder<ITSSAPIContext>()
.UseInMemoryDatabase(databaseName: "ITSSMaster")
.Options;
using (var context = new ITSSAPIContext(options))
{
TrainingRepository trepo = new TrainingRepository(context);
EmployeeRepository erepo = new EmployeeRepository(context);
EmployeeTrainingRepository etrepo = new EmployeeTrainingRepository(context);
// Create
trepo.Create(new Training
{
Id = trainingOneGuid,
Host = "ATS",
Name = "ATS Test Training 1",
StartDate = DateTime.Now,
Facillitator = "Darth Maul",
StipendAmount = 750,
});
trepo.Create(new Training
{
Id = trainingTwoGuid,
Host = "CO",
Name = "CO Test Training 1",
StartDate = DateTime.Now,
Facillitator = "Darth Vader",
StipendAmount = 0
});
erepo.Create(new Employee
{
Id = Guid.Parse("5b1c2b4d-48c7-402a-80c3-cc796ad49c6b"),
OrgDefinedId = 000032615,
Designation = String.Empty
});
erepo.Create(new Employee
{
Id = Guid.Parse("d8663e5e-7494-4f81-8739-6e0de1bea7ee"),
OrgDefinedId = 000012345,
Designation = "Champion"
});
//Training: GetIncluding
Training training1 = trepo.GetIncluding<Training>(
trainingOneGuid,
c => c.EmployeeTrainings);
Assert.Equal("ATS Test Training 1", training1.Name);
Training training2 = trepo.GetIncluding<Training>(
trainingTwoGuid,
c => c.EmployeeTrainings);
Assert.Equal("CO Test Training 1", training2.Name);
//Employee: GetIncluding
Employee employee1 = erepo.GetIncluding<Employee>(
employeeOneGuid,
c => c.EmployeeTrainings);
Assert.Equal(000032615, employee1.OrgDefinedId);
Employee employee2 = erepo.GetIncluding<Employee>(
employeeTwoGuid,
c => c.EmployeeTrainings);
Assert.Equal(000012345, employee2.OrgDefinedId);
//EmployeeTraining: Add
etrepo.AddTrainingToEmployee(employee1, training1);
etrepo.AddTrainingToEmployee(employee2, training1);
Assert.Equal(2, training1.EmployeeTrainings.Count);
etrepo.AddTrainingToEmployee(employee1, training2);
Assert.Equal(1, training2.EmployeeTrainings.Count);
Assert.Equal(2, employee1.EmployeeTrainings.Count);
Assert.Equal(1, employee2.EmployeeTrainings.Count);
//Automapper
var config1 = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Training, TrainingDto>()
.ForMember(dst => dst.EmployeeTrainings,
opt => opt.MapFrom(model => model.EmployeeTrainings));
});
//Using automapper
var mapper1 = new Mapper(config1);
var TrainingDto1 = mapper1.Map<TrainingDto>(training1);
var TrainingDto2 = mapper1.Map<TrainingDto>(training2);
}
}
Watch Window
First, check that you've registered your profiles by calling the IServiceCollection
extension method AddAutoMapper at application startup:
services.AddAutoMapper();
Then, slightly change your EmployeeTrainings
assignment into this:
CreateMap<Training, TrainingDto>()
.ForMember(dst => dst.EmployeeTrainings, opt => opt.MapFrom(model => model.EmployeeTrainings));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.