In my DAL, I have the following models establishing a many-to-many relationship.
public class FamilyMember
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<FamilyMemberPhone> FamilyMemberPhones { get; set; }
}
public class FamilyMemberPhone
{
public int FamilyMemberId { get; set; }
public int PhoneId { get; set; }
public FamilyMember FamilyMember { get; set; }
public Phone Phone { get; set; }
}
public class Phone : AuditableEntity
{
public int Id { get; set; }
public string PhoneNumber { get; set; }
public bool IsPreferred { get; set; }
public ICollection<FamilyMemberPhone> FamilyMemberPhones { get; set; }
}
In my DTO, I have the following classes
public class FamilyMemberDto
{
public int Id { get; set; }
public int FamilyId { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public bool IsPrimary { get; set; }
[Required]
public List<Phone> FamilyMemberPhones { get; set; }
public string FullName => $" {FirstName} {LastName}";
}
public class PhoneDto
{
public int Id { get; set; }
public string PhoneNumber { get; set; }
public bool IsPreferred { get; set; }
public PhoneType PhoneType { get; set; }
}
My Mapping configuration looks like this:
CreateMap<Dal.Models.Phone, Dto.PhoneDto>().ReverseMap().IgnoreAuditableFields();
CreateMap<Dal.Models.FamilyMember, Dto.FamilyMemberDto>();
CreateMap<Dal.Models.FamilyMemberPhone, Dto.PhoneDto>()
.ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id))
.ForMember(d => d.PhoneNumber, opt => opt.MapFrom(s => s.Phone.PhoneNumber))
.ForMember(d => d.PhoneType, opt => opt.MapFrom(s => s.Phone.PhoneType));
CreateMap<Dto.FamilyMemberDto, Dal.Models.FamilyMember>()
.AfterMap((s, d) =>
{
if (d.FamilyMemberPhones != null)
foreach (var fmp in d.FamilyMemberPhones)
fmp.Id = s.Id;
});
CreateMap<Dto.PhoneDto, Dal.Models.FamilyMemberPhone>()
.ForMember(d => d.PhoneId, opt => opt.MapFrom(s => s.Id));
My Unit Test looks like this:
var member = new Bll.Dto.FamilyMemberDto
{
FamilyId = 12,
FirstName = "Jane",
LastName = "Doe",
BirthDate = DateTime.Parse("11-01-1990"),
Email = "test@test.com",
FamilyMemberPhones = new List<Bll.Dto.PhoneDto>
{
new Bll.Dto.PhoneDto
{
PhoneNumber = "test",
IsPreferred = true,
},
new Bll.Dto.Phone
{
PhoneNumber = "hello",
IsPreferred = false,
}
}
};
await Manager.Save(member);
When I'm trying to map the DTO
to Model
using Mapper.Map<Dal.Models.FamilyMember>(dto)
, in the entity.FamilyMemberPhones
object, I see two items in the collection. However, digging deeper into the collection, all Dal.Models.Phone
properties are null.
What am I doing wrong?
From this area of your code
CreateMap<Dto.FamilyMemberDto, Dal.Models.FamilyMember>()
.AfterMap((s, d) =>
{
if (d.FamilyMemberPhones != null)
foreach (var fmp in d.FamilyMemberPhones)
fmp.Id = s.Id;
});
You are assigning a value to a variable created in a loop. That is fmp.Id = s.Id;
maybe instead of s.Id = fmp.Id;
or even something else. Because that doesn't look like you're doing anything there.
@formula12's answer sparked a thought in my head. I need to account for every phone number that is being added to a family member. As the result, every time I am mapping FamilyMemberDto
to FamilyMember
, I need to also account for list of Phone
inside of the map.
This is my new mapping profile:
CreateMap<Phone, Dto.PhoneDto>().ReverseMap().IgnoreAuditableFields();
CreateMap<FamilyMember, Dto.FamilyMemberDto>();
CreateMap<FamilyMemberPhone, Dto.PhoneDto>()
.ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id))
.ForMember(d => d.PhoneNumber, opt => opt.MapFrom(s => s.Phone.PhoneNumber))
.ForMember(d => d.PhoneType, opt => opt.MapFrom(s => s.Phone.PhoneType));
CreateMap<Dto.FamilyMemberDto, FamilyMember>()
.AfterMap((s, d) =>
{
var memberPhones = new List<FamilyMemberPhone>();
foreach (var fmp in s.FamilyMemberPhones)
{
var phone = new FamilyMemberPhone
{
Phone = new Phone
{
Id = fmp.Id,
PhoneNumber = fmp.PhoneNumber,
PhoneType = fmp.PhoneType
}
};
memberPhones.Add(phone);
}
d.FamilyMemberPhones = memberPhones;
});
CreateMap<Dto.PhoneDto, FamilyMemberPhone>()
.ForMember(d => d.PhoneId, opt => opt.MapFrom(s => s.Id));
Used case: Let's say my family member has three (3) items in FaimlyMemberDto.FamilyMemberPhones
which is a List<PhoneDto>
, when going through the mapping process, My entity now has 3 FamilyMemberPhone
objects in the ICollection<FamilyMemberPhones>
in FamilyMember
object. Inside of each of those, there is now a Phone
object that maps to PhoneDto
.
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.